blob: a941ac7a659d9d748799b87c460486cc00997b75 [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,
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200100 Opt_multichannel, Opt_nomultichannel,
Steve French9fe5ff12019-06-24 20:39:04 -0500101 Opt_compress,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400102
103 /* Mount options which take numeric value */
104 Opt_backupuid, Opt_backupgid, Opt_uid,
105 Opt_cruid, Opt_gid, Opt_file_mode,
106 Opt_dirmode, Opt_port,
Steve French563317e2019-09-08 23:22:02 -0500107 Opt_min_enc_offload,
Steve Frenche8506d22019-02-28 21:32:15 -0600108 Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
Steve Frenchca567eb2019-03-29 16:31:07 -0500109 Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200110 Opt_snapshot, Opt_max_channels,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400111
112 /* Mount options which take string value */
113 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400114 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400115 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400116 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400117
118 /* Mount options to be ignored */
119 Opt_ignore,
120
121 /* Options which could be blank */
122 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100123 Opt_blank_user,
124 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400125
126 Opt_err
127};
128
129static const match_table_t cifs_mount_option_tokens = {
130
131 { Opt_user_xattr, "user_xattr" },
132 { Opt_nouser_xattr, "nouser_xattr" },
133 { Opt_forceuid, "forceuid" },
134 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400135 { Opt_forcegid, "forcegid" },
136 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400137 { Opt_noblocksend, "noblocksend" },
138 { Opt_noautotune, "noautotune" },
Steve French3e7a02d2019-09-11 21:46:20 -0500139 { Opt_nolease, "nolease" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400140 { Opt_hard, "hard" },
141 { Opt_soft, "soft" },
142 { Opt_perm, "perm" },
143 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500144 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400145 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500146 { Opt_mapposix, "mapposix" }, /* SFM style */
147 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400148 { Opt_sfu, "sfu" },
149 { Opt_nosfu, "nosfu" },
150 { Opt_nodfs, "nodfs" },
151 { Opt_posixpaths, "posixpaths" },
152 { Opt_noposixpaths, "noposixpaths" },
153 { Opt_nounix, "nounix" },
154 { Opt_nounix, "nolinux" },
Steve Frenchb3266142018-05-20 23:41:10 -0500155 { Opt_nounix, "noposix" },
156 { Opt_unix, "unix" },
157 { Opt_unix, "linux" },
158 { Opt_unix, "posix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400159 { Opt_nocase, "nocase" },
160 { Opt_nocase, "ignorecase" },
161 { Opt_brl, "brl" },
162 { Opt_nobrl, "nobrl" },
Steve French3d4ef9a2018-04-25 22:19:09 -0500163 { Opt_handlecache, "handlecache" },
164 { Opt_nohandlecache, "nohandlecache" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400165 { Opt_nobrl, "nolock" },
166 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400167 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400168 { Opt_setuids, "setuids" },
169 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500170 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400171 { Opt_dynperm, "dynperm" },
172 { Opt_nodynperm, "nodynperm" },
173 { Opt_nohard, "nohard" },
174 { Opt_nosoft, "nosoft" },
175 { Opt_nointr, "nointr" },
176 { Opt_intr, "intr" },
177 { Opt_nostrictsync, "nostrictsync" },
178 { Opt_strictsync, "strictsync" },
179 { Opt_serverino, "serverino" },
180 { Opt_noserverino, "noserverino" },
181 { Opt_rwpidforward, "rwpidforward" },
Steve French412094a2019-06-24 02:01:42 -0500182 { Opt_modesid, "modefromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400183 { Opt_cifsacl, "cifsacl" },
184 { Opt_nocifsacl, "nocifsacl" },
185 { Opt_acl, "acl" },
186 { Opt_noacl, "noacl" },
187 { Opt_locallease, "locallease" },
188 { Opt_sign, "sign" },
Steve French4f5c10f2019-09-03 21:18:49 -0500189 { Opt_ignore_signature, "signloosely" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400190 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400191 { Opt_noac, "noac" },
192 { Opt_fsc, "fsc" },
193 { Opt_mfsymlinks, "mfsymlinks" },
194 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400195 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400196 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500197 { Opt_persistent, "persistenthandles"},
198 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600199 { Opt_resilient, "resilienthandles"},
200 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530201 { Opt_domainauto, "domainauto"},
Long Li8339dd32017-11-07 01:54:55 -0700202 { Opt_rdma, "rdma"},
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200203 { Opt_multichannel, "multichannel" },
204 { Opt_nomultichannel, "nomultichannel" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400205
206 { Opt_backupuid, "backupuid=%s" },
207 { Opt_backupgid, "backupgid=%s" },
208 { Opt_uid, "uid=%s" },
209 { Opt_cruid, "cruid=%s" },
210 { Opt_gid, "gid=%s" },
211 { Opt_file_mode, "file_mode=%s" },
212 { Opt_dirmode, "dirmode=%s" },
213 { Opt_dirmode, "dir_mode=%s" },
214 { Opt_port, "port=%s" },
Steve French563317e2019-09-08 23:22:02 -0500215 { Opt_min_enc_offload, "esize=%s" },
Steve Frenche8506d22019-02-28 21:32:15 -0600216 { Opt_blocksize, "bsize=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400217 { Opt_rsize, "rsize=%s" },
218 { Opt_wsize, "wsize=%s" },
219 { Opt_actimeo, "actimeo=%s" },
Steve Frenchca567eb2019-03-29 16:31:07 -0500220 { Opt_handletimeout, "handletimeout=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600221 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500222 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600223 { Opt_snapshot, "snapshot=%s" },
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200224 { Opt_max_channels, "max_channels=%s" },
Steve French9fe5ff12019-06-24 20:39:04 -0500225 { Opt_compress, "compress=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400226
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100227 { Opt_blank_user, "user=" },
228 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400229 { Opt_user, "user=%s" },
230 { Opt_user, "username=%s" },
231 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100232 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400233 { Opt_pass, "pass=%s" },
234 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100235 { Opt_blank_ip, "ip=" },
236 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400237 { Opt_ip, "ip=%s" },
238 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400239 { Opt_ignore, "unc=%s" },
240 { Opt_ignore, "target=%s" },
241 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400242 { Opt_domain, "dom=%s" },
243 { Opt_domain, "domain=%s" },
244 { Opt_domain, "workgroup=%s" },
245 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400246 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400247 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400248 { Opt_netbiosname, "netbiosname=%s" },
249 { Opt_servern, "servern=%s" },
250 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400251 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400252 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400253 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400254
255 { Opt_ignore, "cred" },
256 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400257 { Opt_ignore, "cred=%s" },
258 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400259 { Opt_ignore, "guest" },
260 { Opt_ignore, "rw" },
261 { Opt_ignore, "ro" },
262 { Opt_ignore, "suid" },
263 { Opt_ignore, "nosuid" },
264 { Opt_ignore, "exec" },
265 { Opt_ignore, "noexec" },
266 { Opt_ignore, "nodev" },
267 { Opt_ignore, "noauto" },
268 { Opt_ignore, "dev" },
269 { Opt_ignore, "mand" },
270 { Opt_ignore, "nomand" },
Steve French9b9c5be2018-09-22 12:07:06 -0500271 { Opt_ignore, "relatime" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400272 { Opt_ignore, "_netdev" },
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -0300273 { Opt_rootfs, "rootfs" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400274
275 { Opt_err, NULL }
276};
277
278enum {
279 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
280 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400281 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
282 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400283 Opt_sec_none,
284
285 Opt_sec_err
286};
287
288static const match_table_t cifs_secflavor_tokens = {
289 { Opt_sec_krb5, "krb5" },
290 { Opt_sec_krb5i, "krb5i" },
291 { Opt_sec_krb5p, "krb5p" },
292 { Opt_sec_ntlmsspi, "ntlmsspi" },
293 { Opt_sec_ntlmssp, "ntlmssp" },
294 { Opt_ntlm, "ntlm" },
295 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400296 { Opt_sec_ntlmv2, "nontlm" },
297 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400298 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400299 { Opt_sec_lanman, "lanman" },
300 { Opt_sec_none, "none" },
301
302 { Opt_sec_err, NULL }
303};
304
Jeff Layton15b6a472012-05-16 07:50:15 -0400305/* cache flavors */
306enum {
307 Opt_cache_loose,
308 Opt_cache_strict,
309 Opt_cache_none,
Steve French83bbfa72019-08-27 23:58:54 -0500310 Opt_cache_ro,
Steve French41e033f2019-08-30 02:12:41 -0500311 Opt_cache_rw,
Jeff Layton15b6a472012-05-16 07:50:15 -0400312 Opt_cache_err
313};
314
315static const match_table_t cifs_cacheflavor_tokens = {
316 { Opt_cache_loose, "loose" },
317 { Opt_cache_strict, "strict" },
318 { Opt_cache_none, "none" },
Steve French83bbfa72019-08-27 23:58:54 -0500319 { Opt_cache_ro, "ro" },
Steve French41e033f2019-08-30 02:12:41 -0500320 { Opt_cache_rw, "singleclient" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400321 { Opt_cache_err, NULL }
322};
323
Jeff Layton23db65f2012-05-15 12:20:51 -0400324static const match_table_t cifs_smb_version_tokens = {
325 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600326 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000327 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500328 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500329 { Smb_302, SMB302_VERSION_STRING },
Kenneth D'souza4a3b38a2018-11-17 10:33:30 +0530330 { Smb_302, ALT_SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600331 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500332 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French9764c022017-09-17 10:41:35 -0500333 { Smb_3any, SMB3ANY_VERSION_STRING },
334 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600335 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400336};
337
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300338static int ip_connect(struct TCP_Server_Info *server);
339static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400340static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400341static void cifs_prune_tlinks(struct work_struct *work);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200342static char *extract_hostname(const char *unc);
343
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200344/*
345 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
346 * get their ip addresses changed at some point.
347 *
348 * This should be called with server->srv_mutex held.
349 */
350#ifdef CONFIG_CIFS_DFS_UPCALL
351static int reconn_set_ipaddr(struct TCP_Server_Info *server)
352{
353 int rc;
354 int len;
355 char *unc, *ipaddr = NULL;
356
357 if (!server->hostname)
358 return -EINVAL;
359
360 len = strlen(server->hostname) + 3;
361
362 unc = kmalloc(len, GFP_KERNEL);
363 if (!unc) {
364 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
365 return -ENOMEM;
366 }
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +1000367 scnprintf(unc, len, "\\\\%s", server->hostname);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200368
369 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
370 kfree(unc);
371
372 if (rc < 0) {
373 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
374 __func__, server->hostname, rc);
375 return rc;
376 }
377
378 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
379 strlen(ipaddr));
380 kfree(ipaddr);
381
382 return !rc ? -1 : 0;
383}
384#else
385static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
386{
387 return 0;
388}
389#endif
390
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200391#ifdef CONFIG_CIFS_DFS_UPCALL
392struct super_cb_data {
393 struct TCP_Server_Info *server;
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300394 struct super_block *sb;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200395};
396
397/* These functions must be called with server->srv_mutex held */
398
399static void super_cb(struct super_block *sb, void *arg)
400{
401 struct super_cb_data *d = arg;
402 struct cifs_sb_info *cifs_sb;
403 struct cifs_tcon *tcon;
404
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300405 if (d->sb)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200406 return;
407
408 cifs_sb = CIFS_SB(sb);
409 tcon = cifs_sb_master_tcon(cifs_sb);
410 if (tcon->ses->server == d->server)
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300411 d->sb = sb;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200412}
413
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300414static struct super_block *get_tcp_super(struct TCP_Server_Info *server)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200415{
416 struct super_cb_data d = {
417 .server = server,
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300418 .sb = NULL,
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200419 };
420
421 iterate_supers_type(&cifs_fs_type, super_cb, &d);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300422
423 if (unlikely(!d.sb))
424 return ERR_PTR(-ENOENT);
425 /*
426 * Grab an active reference in order to prevent automounts (DFS links)
427 * of expiring and then freeing up our cifs superblock pointer while
428 * we're doing failover.
429 */
430 cifs_sb_active(d.sb);
431 return d.sb;
432}
433
434static inline void put_tcp_super(struct super_block *sb)
435{
436 if (!IS_ERR_OR_NULL(sb))
437 cifs_sb_deactive(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200438}
439
440static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
441 struct cifs_sb_info *cifs_sb,
442 struct dfs_cache_tgt_list *tgt_list,
443 struct dfs_cache_tgt_iterator **tgt_it)
444{
445 const char *name;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200446
447 if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list ||
448 !server->nr_targets)
449 return;
450
451 if (!*tgt_it) {
452 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
453 } else {
454 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
455 if (!*tgt_it)
456 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
457 }
458
459 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
460
461 name = dfs_cache_get_tgt_name(*tgt_it);
462
463 kfree(server->hostname);
464
465 server->hostname = extract_hostname(name);
Dan Carpenter84288172019-01-05 15:25:29 +0300466 if (IS_ERR(server->hostname)) {
467 cifs_dbg(FYI,
468 "%s: failed to extract hostname from target: %ld\n",
469 __func__, PTR_ERR(server->hostname));
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200470 }
471}
472
473static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
474 struct dfs_cache_tgt_list *tl,
475 struct dfs_cache_tgt_iterator **it)
476{
477 if (!cifs_sb->origin_fullpath)
478 return -EOPNOTSUPP;
479 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
480}
481#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Jeff Laytond5c56052008-12-01 18:42:33 -0500483/*
484 * cifs tcp session reconnection
485 *
486 * mark tcp session as reconnecting so temporarily locked
487 * mark all smb sessions as reconnecting for tcp session
488 * reconnect tcp session
489 * wake up waiters on reconnection? - (not needed currently)
490 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400491int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492cifs_reconnect(struct TCP_Server_Info *server)
493{
494 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500495 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000496 struct cifs_ses *ses;
497 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000498 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400499 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200500#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300501 struct super_block *sb = NULL;
Paulo Alcantara23324402018-11-20 14:37:18 -0200502 struct cifs_sb_info *cifs_sb = NULL;
503 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200504 struct dfs_cache_tgt_iterator *tgt_it = NULL;
505#endif
Steve French50c2f752007-07-13 00:33:32 +0000506
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200508 server->nr_targets = 1;
509#ifdef CONFIG_CIFS_DFS_UPCALL
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000510 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300511 sb = get_tcp_super(server);
512 if (IS_ERR(sb)) {
513 rc = PTR_ERR(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200514 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
515 __func__, rc);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300516 sb = NULL;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200517 } else {
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300518 cifs_sb = CIFS_SB(sb);
519
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200520 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
Steve French55a7f002019-01-01 17:19:45 -0600521 if (rc && (rc != -EOPNOTSUPP)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000522 cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200523 __func__);
524 } else {
525 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
526 }
527 }
528 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
529 server->nr_targets);
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000530 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200531#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000532 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000533 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 next time through the loop */
535 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300536#ifdef CONFIG_CIFS_DFS_UPCALL
537 dfs_cache_free_tgts(&tgt_list);
538 put_tcp_super(sb);
539#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return rc;
541 } else
542 server->tcpStatus = CifsNeedReconnect;
543 spin_unlock(&GlobalMid_Lock);
544 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400545 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
Steve French6e4d3bb2018-09-22 11:25:04 -0500547 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500548 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
550 /* before reconnecting the tcp session, mark the smb session (uid)
551 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500552 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
553 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530554 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500555 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000556 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500557 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500558 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000559 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500560 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100562 if (ses->tcon_ipc)
563 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530565 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500566
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500568 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500569 mutex_lock(&server->srv_mutex);
Long Li1d2a4f52019-05-13 21:01:28 -0700570 if (server->ssocket) {
571 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
572 server->ssocket->state, server->ssocket->flags);
573 kernel_sock_shutdown(server->ssocket, SHUT_WR);
574 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
575 server->ssocket->state, server->ssocket->flags);
576 sock_release(server->ssocket);
577 server->ssocket = NULL;
578 }
579 server->sequence_number = 0;
580 server->session_estab = false;
581 kfree(server->session_key.response);
582 server->session_key.response = NULL;
583 server->session_key.len = 0;
584 server->lstrp = jiffies;
Long Li214bab42019-04-05 21:36:35 +0000585
586 /* mark submitted MIDs for retry and issue callback */
587 INIT_LIST_HEAD(&retry_list);
588 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
589 spin_lock(&GlobalMid_Lock);
590 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
591 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700592 kref_get(&mid_entry->refcount);
Long Li214bab42019-04-05 21:36:35 +0000593 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
594 mid_entry->mid_state = MID_RETRY_NEEDED;
595 list_move(&mid_entry->qhead, &retry_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700596 mid_entry->mid_flags |= MID_DELETED;
Long Li214bab42019-04-05 21:36:35 +0000597 }
598 spin_unlock(&GlobalMid_Lock);
Long Li1d2a4f52019-05-13 21:01:28 -0700599 mutex_unlock(&server->srv_mutex);
Long Li214bab42019-04-05 21:36:35 +0000600
601 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
602 list_for_each_safe(tmp, tmp2, &retry_list) {
603 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
604 list_del_init(&mid_entry->qhead);
605 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700606 cifs_mid_q_entry_release(mid_entry);
Long Li214bab42019-04-05 21:36:35 +0000607 }
608
Long Li1d2a4f52019-05-13 21:01:28 -0700609 if (cifs_rdma_enabled(server)) {
610 mutex_lock(&server->srv_mutex);
Long Li050b8c32019-04-04 11:35:42 -0500611 smbd_destroy(server);
Long Li1d2a4f52019-05-13 21:01:28 -0700612 mutex_unlock(&server->srv_mutex);
613 }
Jeff Layton3c1105d2011-05-22 07:09:13 -0400614
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400615 do {
Steve French6c3d8902006-07-31 22:46:20 +0000616 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300617
Jeff Layton73e216a2013-09-05 08:38:10 -0400618 mutex_lock(&server->srv_mutex);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200619 /*
620 * Set up next DFS target server (if any) for reconnect. If DFS
621 * feature is disabled, then we will retry last server we
622 * connected to before.
623 */
Long Li781a8052017-11-22 17:38:36 -0700624 if (cifs_rdma_enabled(server))
625 rc = smbd_reconnect(server);
626 else
627 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000628 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500629 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200630#ifdef CONFIG_CIFS_DFS_UPCALL
631 reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
632 &tgt_it);
633#endif
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200634 rc = reconn_set_ipaddr(server);
635 if (rc) {
636 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
637 __func__, rc);
638 }
Federico Sauter4afe2602015-03-17 17:45:28 +0100639 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700640 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 } else {
642 atomic_inc(&tcpSesReconnectCount);
Pavel Shilovsky335b7b62019-01-16 11:12:41 -0800643 set_credits(server, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000645 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000646 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000647 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100648 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400650 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500651
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200652#ifdef CONFIG_CIFS_DFS_UPCALL
653 if (tgt_it) {
654 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
655 tgt_it);
656 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000657 cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200658 __func__, rc);
659 }
660 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
661 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000662 cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200663 __func__, rc);
664 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200665 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300666
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200667 }
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300668
669 put_tcp_super(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200670#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400671 if (server->tcpStatus == CifsNeedNegotiate)
672 mod_delayed_work(cifsiod_wq, &server->echo, 0);
673
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 return rc;
675}
676
Jeff Laytonc74093b2011-01-11 07:24:23 -0500677static void
678cifs_echo_request(struct work_struct *work)
679{
680 int rc;
681 struct TCP_Server_Info *server = container_of(work,
682 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400683 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500684
Jeff Layton247ec9b2011-02-04 17:09:50 -0500685 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400686 * If we need to renegotiate, set echo interval to zero to
687 * immediately call echo service where we can renegotiate.
688 */
689 if (server->tcpStatus == CifsNeedNegotiate)
690 echo_interval = 0;
691 else
692 echo_interval = server->echo_interval;
693
694 /*
695 * We cannot send an echo if it is disabled.
696 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500697 */
Steve French4fcd1812016-06-22 20:12:05 -0500698
699 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400700 server->tcpStatus == CifsExiting ||
701 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400702 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600703 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500704 goto requeue_echo;
705
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400706 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500707 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500708 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
709 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500710
711requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400712 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500713}
714
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400715static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400716allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400717{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400718 if (!server->bigbuf) {
719 server->bigbuf = (char *)cifs_buf_get();
720 if (!server->bigbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000721 cifs_server_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400722 msleep(3000);
723 /* retry will check if exiting */
724 return false;
725 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400726 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400727 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400728 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400729 }
730
Jeff Layton2a37ef92011-10-19 15:29:23 -0400731 if (!server->smallbuf) {
732 server->smallbuf = (char *)cifs_small_buf_get();
733 if (!server->smallbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000734 cifs_server_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400735 msleep(1000);
736 /* retry will check if exiting */
737 return false;
738 }
739 /* beginning of smb buffer is cleared in our buf_get */
740 } else {
741 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400742 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400743 }
744
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400745 return true;
746}
747
Jeff Laytonba749e62011-10-11 06:41:32 -0400748static bool
749server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400750{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300751 /*
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000752 * We need to wait 3 echo intervals to make sure we handle such
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300753 * situations right:
754 * 1s client sends a normal SMB request
Ronnie Sahlbergbecc2ba2019-07-24 11:43:49 +1000755 * 2s client gets a response
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300756 * 30s echo workqueue job pops, and decides we got a response recently
757 * and don't need to send another
758 * ...
759 * 65s kernel_recvmsg times out, and we see that we haven't gotten
760 * a response in >60s.
761 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200762 if ((server->tcpStatus == CifsGood ||
763 server->tcpStatus == CifsNeedNegotiate) &&
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000764 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000765 cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
766 (3 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400767 cifs_reconnect(server);
768 wake_up(&server->response_q);
769 return true;
770 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400771
Jeff Laytonba749e62011-10-11 06:41:32 -0400772 return false;
773}
774
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800775static inline bool
776zero_credits(struct TCP_Server_Info *server)
777{
778 int val;
779
780 spin_lock(&server->req_lock);
781 val = server->credits + server->echo_credits + server->oplock_credits;
782 if (server->in_flight == 0 && val == 0) {
783 spin_unlock(&server->req_lock);
784 return true;
785 }
786 spin_unlock(&server->req_lock);
787 return false;
788}
789
Al Viro71335662016-01-09 19:54:50 -0500790static int
791cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400792{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400793 int length = 0;
794 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400795
Al Viro71335662016-01-09 19:54:50 -0500796 smb_msg->msg_control = NULL;
797 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400798
Al Viro71335662016-01-09 19:54:50 -0500799 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500800 try_to_freeze();
801
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800802 /* reconnect if no credits and no requests in flight */
803 if (zero_credits(server)) {
804 cifs_reconnect(server);
805 return -ECONNABORTED;
806 }
807
Al Viro71335662016-01-09 19:54:50 -0500808 if (server_unresponsive(server))
809 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700810 if (cifs_rdma_enabled(server) && server->smbd_conn)
811 length = smbd_recv(server->smbd_conn, smb_msg);
812 else
813 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500814
815 if (server->tcpStatus == CifsExiting)
816 return -ESHUTDOWN;
817
818 if (server->tcpStatus == CifsNeedReconnect) {
819 cifs_reconnect(server);
820 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400821 }
822
Al Viro71335662016-01-09 19:54:50 -0500823 if (length == -ERESTARTSYS ||
824 length == -EAGAIN ||
825 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400826 /*
827 * Minimum sleep to prevent looping, allowing socket
828 * to clear and app threads to set tcpStatus
829 * CifsNeedReconnect if server hung.
830 */
831 usleep_range(1000, 2000);
832 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400833 continue;
Al Viro71335662016-01-09 19:54:50 -0500834 }
835
836 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500837 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400838 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500839 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400840 }
841 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400842 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400843}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400844
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400845int
846cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
847 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400848{
Al Viro71335662016-01-09 19:54:50 -0500849 struct msghdr smb_msg;
850 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100851 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400852
Al Viro71335662016-01-09 19:54:50 -0500853 return cifs_readv_from_socket(server, &smb_msg);
854}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400855
Al Viro71335662016-01-09 19:54:50 -0500856int
857cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700858 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500859{
860 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700861 struct bio_vec bv = {
862 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100863 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500864 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400865}
866
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400867static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400868is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400869{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400870 /*
871 * The first byte big endian of the length field,
872 * is actually not part of the length but the type
873 * with the most common, zero, as regular data.
874 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400875 switch (type) {
876 case RFC1002_SESSION_MESSAGE:
877 /* Regular SMB response */
878 return true;
879 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500880 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400881 break;
882 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500883 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400884 break;
885 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400886 /*
887 * We get this from Windows 98 instead of an error on
888 * SMB negprot response.
889 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500890 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400891 /* give server a second to clean up */
892 msleep(1000);
893 /*
894 * Always try 445 first on reconnect since we get NACK
895 * on some if we ever connected to port 139 (the NACK
896 * is since we do not begin with RFC1001 session
897 * initialize frame).
898 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400899 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400900 cifs_reconnect(server);
901 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400902 break;
903 default:
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000904 cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400905 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400906 }
907
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400908 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400909}
910
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400911void
912dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400913{
914#ifdef CONFIG_CIFS_STATS2
915 mid->when_received = jiffies;
916#endif
917 spin_lock(&GlobalMid_Lock);
918 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400919 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400920 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400921 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000922 /*
923 * Trying to handle/dequeue a mid after the send_recv()
924 * function has finished processing it is a bug.
925 */
926 if (mid->mid_flags & MID_DELETED)
927 printk_once(KERN_WARNING
928 "trying to dequeue a deleted mid\n");
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700929 else {
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000930 list_del_init(&mid->qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700931 mid->mid_flags |= MID_DELETED;
932 }
Jeff Laytonea1f4502011-10-19 15:29:05 -0400933 spin_unlock(&GlobalMid_Lock);
934}
935
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800936static unsigned int
937smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
938{
939 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
940
941 /*
942 * SMB1 does not use credits.
943 */
944 if (server->vals->header_preamble_size)
945 return 0;
946
947 return le16_to_cpu(shdr->CreditRequest);
948}
949
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400950static void
951handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400952 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400953{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400954 if (server->ops->check_trans2 &&
955 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400956 return;
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800957 mid->credits_received = smb2_get_credits_from_hdr(buf, server);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400958 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400959 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400960 /* Was previous buf put in mpx struct for multi-rsp? */
961 if (!mid->multiRsp) {
962 /* smb buffer will be freed by user thread */
963 if (server->large_buf)
964 server->bigbuf = NULL;
965 else
966 server->smallbuf = NULL;
967 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400968 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400969}
970
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400971static void clean_demultiplex_info(struct TCP_Server_Info *server)
972{
973 int length;
974
975 /* take it off the list, if it's not already */
976 spin_lock(&cifs_tcp_ses_lock);
977 list_del_init(&server->tcp_ses_list);
978 spin_unlock(&cifs_tcp_ses_lock);
979
980 spin_lock(&GlobalMid_Lock);
981 server->tcpStatus = CifsExiting;
982 spin_unlock(&GlobalMid_Lock);
983 wake_up_all(&server->response_q);
984
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400985 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300986 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400987 if (server->credits <= 0)
988 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300989 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400990 /*
991 * Although there should not be any requests blocked on this queue it
992 * can not hurt to be paranoid and try to wake up requests that may
993 * haven been blocked when more than 50 at time were on the wire to the
994 * same server - they now will see the session is in exit state and get
995 * out of SendReceive.
996 */
997 wake_up_all(&server->request_q);
998 /* give those requests time to exit */
999 msleep(125);
Long Li050b8c32019-04-04 11:35:42 -05001000 if (cifs_rdma_enabled(server))
1001 smbd_destroy(server);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001002 if (server->ssocket) {
1003 sock_release(server->ssocket);
1004 server->ssocket = NULL;
1005 }
1006
1007 if (!list_empty(&server->pending_mid_q)) {
1008 struct list_head dispose_list;
1009 struct mid_q_entry *mid_entry;
1010 struct list_head *tmp, *tmp2;
1011
1012 INIT_LIST_HEAD(&dispose_list);
1013 spin_lock(&GlobalMid_Lock);
1014 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
1015 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -05001016 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovskyabe57072019-10-22 08:41:42 -07001017 kref_get(&mid_entry->refcount);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -04001018 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001019 list_move(&mid_entry->qhead, &dispose_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -07001020 mid_entry->mid_flags |= MID_DELETED;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001021 }
1022 spin_unlock(&GlobalMid_Lock);
1023
1024 /* now walk dispose list and issue callbacks */
1025 list_for_each_safe(tmp, tmp2, &dispose_list) {
1026 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -05001027 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001028 list_del_init(&mid_entry->qhead);
1029 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -07001030 cifs_mid_q_entry_release(mid_entry);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001031 }
1032 /* 1/8th of sec is more than enough time for them to exit */
1033 msleep(125);
1034 }
1035
1036 if (!list_empty(&server->pending_mid_q)) {
1037 /*
1038 * mpx threads have not exited yet give them at least the smb
1039 * send timeout time for long ops.
1040 *
1041 * Due to delays on oplock break requests, we need to wait at
1042 * least 45 seconds before giving up on a request getting a
1043 * response and going ahead and killing cifsd.
1044 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001045 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001046 msleep(46000);
1047 /*
1048 * If threads still have not exited they are probably never
1049 * coming home not much else we can do but free the memory.
1050 */
1051 }
1052
1053 kfree(server->hostname);
1054 kfree(server);
1055
1056 length = atomic_dec_return(&tcpSesAllocCount);
1057 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -07001058 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001059}
1060
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001061static int
Jeff Laytone9097ab2011-10-19 15:29:40 -04001062standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1063{
1064 int length;
1065 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +10001066 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001067
1068 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001069 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
1070 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001071 cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001072 cifs_reconnect(server);
1073 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +04001074 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001075 }
1076
1077 /* switch to large buffer if too big for a small one */
1078 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
1079 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001080 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001081 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001082 }
1083
1084 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001085 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001086 pdu_length - HEADER_SIZE(server) + 1
1087 + server->vals->header_preamble_size);
1088
Jeff Laytone9097ab2011-10-19 15:29:40 -04001089 if (length < 0)
1090 return length;
1091 server->total_read += length;
1092
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001093 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001094
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08001095 return cifs_handle_standard(server, mid);
1096}
1097
1098int
1099cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1100{
1101 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1102 int length;
1103
Jeff Laytone9097ab2011-10-19 15:29:40 -04001104 /*
1105 * We know that we received enough to get to the MID as we
1106 * checked the pdu_length earlier. Now check to see
1107 * if the rest of the header is OK. We borrow the length
1108 * var for the rest of the loop to avoid a new stack var.
1109 *
1110 * 48 bytes is enough to display the header and a little bit
1111 * into the payload for debugging purposes.
1112 */
Steve French373512e2015-12-18 13:05:30 -06001113 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001114 if (length != 0)
1115 cifs_dump_mem("Bad SMB: ", buf,
1116 min_t(unsigned int, server->total_read, 48));
1117
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001118 if (server->ops->is_session_expired &&
1119 server->ops->is_session_expired(buf)) {
1120 cifs_reconnect(server);
1121 wake_up(&server->response_q);
1122 return -1;
1123 }
1124
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001125 if (server->ops->is_status_pending &&
Pavel Shilovsky66265f12019-01-23 17:11:16 -08001126 server->ops->is_status_pending(buf, server))
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001127 return -1;
1128
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001129 if (!mid)
1130 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001131
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001132 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001133 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001134}
1135
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001136static void
1137smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
1138{
1139 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
1140
1141 /*
1142 * SMB1 does not use credits.
1143 */
1144 if (server->vals->header_preamble_size)
1145 return;
1146
1147 if (shdr->CreditRequest) {
1148 spin_lock(&server->req_lock);
1149 server->credits += le16_to_cpu(shdr->CreditRequest);
1150 spin_unlock(&server->req_lock);
1151 wake_up(&server->request_q);
1152 }
1153}
1154
1155
Jeff Laytone9097ab2011-10-19 15:29:40 -04001156static int
Al Viro7c97c202011-06-21 08:51:28 -04001157cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001159 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001160 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001161 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001162 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001163 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001164 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001165 struct mid_q_entry *mids[MAX_COMPOUND];
1166 char *bufs[MAX_COMPOUND];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -05001169 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001170
1171 length = atomic_inc_return(&tcpSesAllocCount);
1172 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001173 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001175 set_freezable();
Eric W. Biederman33da8e72019-08-16 12:33:54 -05001176 allow_kernel_signal(SIGKILL);
Jeff Layton469ee612008-10-16 18:46:39 +00001177 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001178 if (try_to_freeze())
1179 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001180
Jeff Layton2a37ef92011-10-19 15:29:23 -04001181 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001182 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001183
Jeff Layton2a37ef92011-10-19 15:29:23 -04001184 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001185 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001186 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001187
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001188 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001189 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001190 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001191
1192 if (server->vals->header_preamble_size == 0)
1193 server->total_read = 0;
1194 else
1195 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001196
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001197 /*
1198 * The right amount was read from socket - 4 bytes,
1199 * so we can now interpret the length field.
1200 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001201 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001202
Joe Perchesf96637b2013-05-04 22:12:25 -05001203 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001204 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001205 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001206next_pdu:
1207 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001208
Jeff Layton89482a52011-10-19 15:28:57 -04001209 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001210 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001211 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001212 cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001213 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001214 cifs_reconnect(server);
1215 wake_up(&server->response_q);
1216 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001217 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001218
Jeff Layton89482a52011-10-19 15:28:57 -04001219 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001220 length = cifs_read_from_socket(server,
1221 buf + server->vals->header_preamble_size,
1222 HEADER_SIZE(server) - 1
1223 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001224 if (length < 0)
1225 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001226 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001227
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001228 if (server->ops->next_header) {
1229 next_offset = server->ops->next_header(buf);
1230 if (next_offset)
1231 server->pdu_size = next_offset;
1232 }
1233
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001234 memset(mids, 0, sizeof(mids));
1235 memset(bufs, 0, sizeof(bufs));
1236 num_mids = 0;
1237
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001238 if (server->ops->is_transform_hdr &&
1239 server->ops->receive_transform &&
1240 server->ops->is_transform_hdr(buf)) {
1241 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001242 mids,
1243 bufs,
1244 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001245 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001246 mids[0] = server->ops->find_mid(server, buf);
1247 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001248 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001249
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001250 if (!mids[0] || !mids[0]->receive)
1251 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001252 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001253 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001254 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001255
Lars Persson696e4202018-06-25 14:05:25 +02001256 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001257 for (i = 0; i < num_mids; i++)
1258 if (mids[i])
1259 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001260 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001261 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001262
Steve Frenchfda35942011-01-20 18:06:34 +00001263 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001264
1265 for (i = 0; i < num_mids; i++) {
1266 if (mids[i] != NULL) {
1267 mids[i]->resp_buf_size = server->pdu_size;
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001268
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001269 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1270 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001271
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001272 cifs_mid_q_entry_release(mids[i]);
1273 } else if (server->ops->is_oplock_break &&
1274 server->ops->is_oplock_break(bufs[i],
1275 server)) {
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001276 smb2_add_credits_from_hdr(bufs[i], server);
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001277 cifs_dbg(FYI, "Received oplock break\n");
1278 } else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001279 cifs_server_dbg(VFS, "No task to wake, unknown frame "
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001280 "received! NumMids %d\n",
1281 atomic_read(&midCount));
1282 cifs_dump_mem("Received Data is: ", bufs[i],
1283 HEADER_SIZE(server));
Ronnie Sahlberg3e272572019-07-06 06:43:08 +10001284 smb2_add_credits_from_hdr(bufs[i], server);
Steve French39798772006-05-31 22:40:51 +00001285#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001286 if (server->ops->dump_detail)
1287 server->ops->dump_detail(bufs[i],
1288 server);
1289 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001290#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001291 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001292 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001293
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001294 if (pdu_length > server->pdu_size) {
1295 if (!allocate_buffers(server))
1296 continue;
1297 pdu_length -= server->pdu_size;
1298 server->total_read = 0;
1299 server->large_buf = false;
1300 buf = server->smallbuf;
1301 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001302 }
1303 } /* end while !EXITING */
1304
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001305 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001306 cifs_buf_release(server->bigbuf);
1307 if (server->smallbuf) /* no sense logging a debug message if NULL */
1308 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001310 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001311 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001312
1313 /* if server->tsk was NULL then wait for a signal before exiting */
1314 if (!task_to_wake) {
1315 set_current_state(TASK_INTERRUPTIBLE);
1316 while (!signal_pending(current)) {
1317 schedule();
1318 set_current_state(TASK_INTERRUPTIBLE);
1319 }
1320 set_current_state(TASK_RUNNING);
1321 }
1322
Jeff Layton0468a2c2008-12-01 07:09:35 -05001323 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324}
1325
Jeff Laytonc359cf32007-11-16 22:22:06 +00001326/* extract the host portion of the UNC string */
1327static char *
1328extract_hostname(const char *unc)
1329{
1330 const char *src;
1331 char *dst, *delim;
1332 unsigned int len;
1333
1334 /* skip double chars at beginning of string */
1335 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001336 if (strlen(unc) < 3)
1337 return ERR_PTR(-EINVAL);
1338 for (src = unc; *src && *src == '\\'; src++)
1339 ;
1340 if (!*src)
1341 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001342
1343 /* delimiter between hostname and sharename is always '\\' now */
1344 delim = strchr(src, '\\');
1345 if (!delim)
1346 return ERR_PTR(-EINVAL);
1347
1348 len = delim - src;
1349 dst = kmalloc((len + 1), GFP_KERNEL);
1350 if (dst == NULL)
1351 return ERR_PTR(-ENOMEM);
1352
1353 memcpy(dst, src, len);
1354 dst[len] = '\0';
1355
1356 return dst;
1357}
1358
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001359static int get_option_ul(substring_t args[], unsigned long *option)
1360{
1361 int rc;
1362 char *string;
1363
1364 string = match_strdup(args);
1365 if (string == NULL)
1366 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001367 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001368 kfree(string);
1369
1370 return rc;
1371}
1372
Eric W. Biederman3da46562013-02-06 01:37:39 -08001373static int get_option_uid(substring_t args[], kuid_t *result)
1374{
1375 unsigned long value;
1376 kuid_t uid;
1377 int rc;
1378
1379 rc = get_option_ul(args, &value);
1380 if (rc)
1381 return rc;
1382
1383 uid = make_kuid(current_user_ns(), value);
1384 if (!uid_valid(uid))
1385 return -EINVAL;
1386
1387 *result = uid;
1388 return 0;
1389}
1390
1391static int get_option_gid(substring_t args[], kgid_t *result)
1392{
1393 unsigned long value;
1394 kgid_t gid;
1395 int rc;
1396
1397 rc = get_option_ul(args, &value);
1398 if (rc)
1399 return rc;
1400
1401 gid = make_kgid(current_user_ns(), value);
1402 if (!gid_valid(gid))
1403 return -EINVAL;
1404
1405 *result = gid;
1406 return 0;
1407}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001408
1409static int cifs_parse_security_flavors(char *value,
1410 struct smb_vol *vol)
1411{
1412
1413 substring_t args[MAX_OPT_ARGS];
1414
Jeff Layton1e3cc572013-06-10 17:12:23 -05001415 /*
1416 * With mount options, the last one should win. Reset any existing
1417 * settings back to default.
1418 */
1419 vol->sectype = Unspecified;
1420 vol->sign = false;
1421
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001422 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001423 case Opt_sec_krb5p:
1424 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1425 return 1;
1426 case Opt_sec_krb5i:
1427 vol->sign = true;
1428 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001429 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001430 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001431 break;
1432 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001433 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001434 /* Fallthrough */
1435 case Opt_sec_ntlmssp:
1436 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001437 break;
1438 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001439 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001440 /* Fallthrough */
1441 case Opt_ntlm:
1442 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001443 break;
1444 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001445 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001446 /* Fallthrough */
1447 case Opt_sec_ntlmv2:
1448 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001449 break;
1450#ifdef CONFIG_CIFS_WEAK_PW_HASH
1451 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001452 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001453 break;
1454#endif
1455 case Opt_sec_none:
1456 vol->nullauth = 1;
1457 break;
1458 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001459 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 return 1;
1461 }
1462
1463 return 0;
1464}
1465
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001467cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1468{
1469 substring_t args[MAX_OPT_ARGS];
1470
1471 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1472 case Opt_cache_loose:
1473 vol->direct_io = false;
1474 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001475 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001476 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001477 break;
1478 case Opt_cache_strict:
1479 vol->direct_io = false;
1480 vol->strict_io = true;
Steve French83bbfa72019-08-27 23:58:54 -05001481 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001482 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001483 break;
1484 case Opt_cache_none:
1485 vol->direct_io = true;
1486 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001487 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001488 vol->cache_rw = false;
Steve French83bbfa72019-08-27 23:58:54 -05001489 break;
1490 case Opt_cache_ro:
1491 vol->direct_io = false;
1492 vol->strict_io = false;
1493 vol->cache_ro = true;
Steve French41e033f2019-08-30 02:12:41 -05001494 vol->cache_rw = false;
1495 break;
1496 case Opt_cache_rw:
1497 vol->direct_io = false;
1498 vol->strict_io = false;
1499 vol->cache_ro = false;
1500 vol->cache_rw = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001501 break;
1502 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001503 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001504 return 1;
1505 }
1506 return 0;
1507}
1508
1509static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001510cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001511{
1512 substring_t args[MAX_OPT_ARGS];
1513
1514 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001515#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001516 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001517 if (disable_legacy_dialects) {
1518 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1519 return 1;
1520 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001521 if (is_smb3) {
1522 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1523 return 1;
1524 }
Jeff Layton23db65f2012-05-15 12:20:51 -04001525 vol->ops = &smb1_operations;
1526 vol->vals = &smb1_values;
1527 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001528 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001529 if (disable_legacy_dialects) {
1530 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1531 return 1;
1532 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001533 if (is_smb3) {
1534 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1535 return 1;
1536 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001537 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001538 vol->vals = &smb20_values;
1539 break;
Steve French74204512018-06-19 14:34:08 -05001540#else
1541 case Smb_1:
1542 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1543 return 1;
1544 case Smb_20:
1545 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1546 return 1;
1547#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001548 case Smb_21:
1549 vol->ops = &smb21_operations;
1550 vol->vals = &smb21_values;
1551 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001552 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001553 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001554 vol->vals = &smb30_values;
1555 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001556 case Smb_302:
1557 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1558 vol->vals = &smb302_values;
1559 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001560 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001561 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001562 vol->vals = &smb311_values;
1563 break;
Steve French9764c022017-09-17 10:41:35 -05001564 case Smb_3any:
1565 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1566 vol->vals = &smb3any_values;
1567 break;
1568 case Smb_default:
1569 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1570 vol->vals = &smbdefault_values;
1571 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001572 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001573 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001574 return 1;
1575 }
1576 return 0;
1577}
1578
Jeff Laytond387a5c2012-12-10 06:10:46 -05001579/*
1580 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1581 * fields with the result. Returns 0 on success and an error otherwise.
1582 */
1583static int
1584cifs_parse_devname(const char *devname, struct smb_vol *vol)
1585{
1586 char *pos;
1587 const char *delims = "/\\";
1588 size_t len;
1589
Yao Liu68e26722019-01-28 19:47:28 +08001590 if (unlikely(!devname || !*devname)) {
1591 cifs_dbg(VFS, "Device name not specified.\n");
1592 return -EINVAL;
1593 }
1594
Jeff Laytond387a5c2012-12-10 06:10:46 -05001595 /* make sure we have a valid UNC double delimiter prefix */
1596 len = strspn(devname, delims);
1597 if (len != 2)
1598 return -EINVAL;
1599
1600 /* find delimiter between host and sharename */
1601 pos = strpbrk(devname + 2, delims);
1602 if (!pos)
1603 return -EINVAL;
1604
1605 /* skip past delimiter */
1606 ++pos;
1607
1608 /* now go until next delimiter or end of string */
1609 len = strcspn(pos, delims);
1610
1611 /* move "pos" up to delimiter or NULL */
1612 pos += len;
1613 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1614 if (!vol->UNC)
1615 return -ENOMEM;
1616
1617 convert_delimiter(vol->UNC, '\\');
1618
Sachin Prabhu11e31642016-02-08 13:44:01 +05301619 /* skip any delimiter */
1620 if (*pos == '/' || *pos == '\\')
1621 pos++;
1622
1623 /* If pos is NULL then no prepath */
1624 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001625 return 0;
1626
1627 vol->prepath = kstrdup(pos, GFP_KERNEL);
1628 if (!vol->prepath)
1629 return -ENOMEM;
1630
1631 return 0;
1632}
1633
Jeff Layton23db65f2012-05-15 12:20:51 -04001634static int
Sean Finneyb9468452011-04-11 13:19:32 +00001635cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001636 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001638 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001639 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 unsigned int temp_len, i, j;
1641 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001642 short int override_uid = -1;
1643 short int override_gid = -1;
1644 bool uid_specified = false;
1645 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001646 bool sloppy = false;
1647 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001648 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001649 char *string = NULL;
1650 char *tmp_end, *value;
1651 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001652 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001653 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001654 unsigned short port = 0;
1655 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656
1657 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001658 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001659 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660
Jeff Layton6ee95422012-11-26 11:09:57 -05001661 /* ensure we always start with zeroed-out smb_vol */
1662 memset(vol, 0, sizeof(*vol));
1663
Jeff Layton88463992010-11-22 15:31:03 -05001664 /*
1665 * does not have to be perfect mapping since field is
1666 * informational, only used for servers that do not support
1667 * port 445 and it can be overridden at mount time
1668 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001669 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1670 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001671 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1672
Jeff Layton1397f2e2011-01-07 11:30:28 -05001673 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001674 /* null target name indicates to use *SMBSERVR default called name
1675 if we end up sending RFC1001 session initialize */
1676 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001677 vol->cred_uid = current_uid();
1678 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001679 vol->linux_gid = current_gid();
Steve Frenche8506d22019-02-28 21:32:15 -06001680 vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
Steve French2baa2682014-09-27 02:19:01 -05001681 /*
1682 * default to SFM style remapping of seven reserved characters
1683 * unless user overrides it or we negotiate CIFS POSIX where
1684 * it is unnecessary. Can not simultaneously use more than one mapping
1685 * since then readdir could list files that open could not open
1686 */
1687 vol->remap = true;
1688
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001689 /* default to only allowing write access to owner of the mount */
1690 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
1692 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001693 /* default is always to request posix paths. */
1694 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001695 /* default to using server inode numbers where available */
1696 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001697
Jeff Layton1b359202012-09-19 15:20:27 -07001698 /* default is to use strict cifs caching semantics */
1699 vol->strict_io = true;
1700
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301701 vol->actimeo = CIFS_DEF_ACTIMEO;
1702
Steve Frenchca567eb2019-03-29 16:31:07 -05001703 /* Most clients set timeout to 0, allows server to use its default */
1704 vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1705
Steve French9764c022017-09-17 10:41:35 -05001706 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1707 vol->ops = &smb30_operations;
1708 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001709
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001710 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1711
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001712 /* default to no multichannel (single server connection) */
1713 vol->multichannel = false;
1714 vol->max_channels = 1;
1715
Sean Finneyb9468452011-04-11 13:19:32 +00001716 if (!mountdata)
1717 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
Sean Finneyb9468452011-04-11 13:19:32 +00001719 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1720 if (!mountdata_copy)
1721 goto cifs_parse_mount_err;
1722
1723 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001724 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001725
Steve French50c2f752007-07-13 00:33:32 +00001726 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001727 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 separator[0] = options[4];
1729 options += 5;
1730 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001731 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 }
1733 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001734 vol->backupuid_specified = false; /* no backup intent for a user */
1735 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001736
Jeff Layton37d4f992013-05-24 07:40:05 -04001737 switch (cifs_parse_devname(devname, vol)) {
1738 case 0:
1739 break;
1740 case -ENOMEM:
1741 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1742 goto cifs_parse_mount_err;
1743 case -EINVAL:
1744 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1745 goto cifs_parse_mount_err;
1746 default:
1747 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1748 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001749 }
1750
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001752 substring_t args[MAX_OPT_ARGS];
1753 unsigned long option;
1754 int token;
1755
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 if (!*data)
1757 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001759 token = match_token(data, cifs_mount_option_tokens, args);
1760
1761 switch (token) {
1762
1763 /* Ingnore the following */
1764 case Opt_ignore:
1765 break;
1766
1767 /* Boolean values */
1768 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001770 break;
1771 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001773 break;
1774 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001775 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001776 break;
1777 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001778 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001779 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001780 case Opt_forcegid:
1781 override_gid = 1;
1782 break;
1783 case Opt_noforcegid:
1784 override_gid = 0;
1785 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001786 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001787 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001788 break;
1789 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001790 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001791 break;
Steve French3e7a02d2019-09-11 21:46:20 -05001792 case Opt_nolease:
1793 vol->no_lease = 1;
1794 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001795 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001797 break;
1798 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001800 break;
1801 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 break;
1804 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001806 break;
1807 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001808 vol->sfu_remap = true;
1809 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001810 break;
1811 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001812 vol->sfu_remap = false;
1813 break;
1814 case Opt_mapposix:
1815 vol->remap = true;
1816 vol->sfu_remap = false; /* disable SFU mapping */
1817 break;
1818 case Opt_nomapposix:
1819 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001820 break;
1821 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001822 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001823 break;
1824 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001825 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001826 break;
1827 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001828 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001829 break;
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03001830 case Opt_rootfs:
1831#ifdef CONFIG_CIFS_ROOT
1832 vol->rootfs = true;
1833#endif
1834 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001835 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001836 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001837 break;
1838 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001839 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001840 break;
1841 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001842 if (vol->linux_ext)
1843 cifs_dbg(VFS,
1844 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001845 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001846 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001847 case Opt_unix:
1848 if (vol->no_linux_ext)
1849 cifs_dbg(VFS,
1850 "conflicting unix mount options\n");
1851 vol->linux_ext = 1;
1852 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001853 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001854 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001855 break;
1856 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001857 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001858 break;
1859 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001860 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001861 /*
1862 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001863 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001864 * local vfs will do advisory
1865 */
Steve French50c2f752007-07-13 00:33:32 +00001866 if (vol->file_mode ==
1867 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001868 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001869 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001870 case Opt_nohandlecache:
1871 vol->nohandlecache = 1;
1872 break;
1873 case Opt_handlecache:
1874 vol->nohandlecache = 0;
1875 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001876 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001877 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001878 break;
1879 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001881 break;
1882 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001884 break;
Steve French95932652016-09-23 01:36:34 -05001885 case Opt_setuidfromacl:
1886 vol->setuidfromacl = 1;
1887 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001888 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001889 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001890 break;
1891 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001892 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001893 break;
1894 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001896 break;
1897 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001899 break;
1900 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001902 break;
1903 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001905 break;
1906 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001907 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001908 break;
1909 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001910 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001911 break;
1912 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001914 break;
1915 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001917 break;
1918 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001919 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001920 break;
Steve French412094a2019-06-24 02:01:42 -05001921 case Opt_modesid:
1922 vol->mode_ace = 1;
1923 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001924 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001925 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001926 break;
1927 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001928 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001929 break;
1930 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001932 break;
1933 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001935 break;
1936 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001937 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001938 break;
1939 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001940 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001941 break;
Steve French4f5c10f2019-09-03 21:18:49 -05001942 case Opt_ignore_signature:
1943 vol->sign = true;
1944 vol->ignore_signature = true;
1945 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001946 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001947 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001948 * is a per tree connection (mount) not a per socket
1949 * or per-smb connection option in the protocol
1950 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1951 */
Steve French95b1cb92008-05-15 16:44:38 +00001952 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001953 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001954 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001955 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001956 break;
1957 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301958#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001959 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001960 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301961#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301962 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001963 break;
1964 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001965 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001966 break;
1967 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001968 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001969 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001970 case Opt_sloppy:
1971 sloppy = true;
1972 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001973 case Opt_nosharesock:
1974 vol->nosharesock = true;
1975 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001976 case Opt_nopersistent:
1977 vol->nopersistent = true;
1978 if (vol->persistent) {
1979 cifs_dbg(VFS,
1980 "persistenthandles mount options conflict\n");
1981 goto cifs_parse_mount_err;
1982 }
1983 break;
1984 case Opt_persistent:
1985 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001986 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001987 cifs_dbg(VFS,
1988 "persistenthandles mount options conflict\n");
1989 goto cifs_parse_mount_err;
1990 }
1991 break;
Steve French592fafe2015-11-03 10:08:53 -06001992 case Opt_resilient:
1993 vol->resilient = true;
1994 if (vol->persistent) {
1995 cifs_dbg(VFS,
1996 "persistenthandles mount options conflict\n");
1997 goto cifs_parse_mount_err;
1998 }
1999 break;
2000 case Opt_noresilient:
2001 vol->resilient = false; /* already the default */
2002 break;
Germano Percossi39566442016-12-15 12:31:18 +05302003 case Opt_domainauto:
2004 vol->domainauto = true;
2005 break;
Long Li8339dd32017-11-07 01:54:55 -07002006 case Opt_rdma:
2007 vol->rdma = true;
2008 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002009 case Opt_multichannel:
2010 vol->multichannel = true;
2011 break;
2012 case Opt_nomultichannel:
2013 vol->multichannel = false;
2014 break;
Steve French9fe5ff12019-06-24 20:39:04 -05002015 case Opt_compress:
2016 vol->compression = UNKNOWN_TYPE;
2017 cifs_dbg(VFS,
2018 "SMB3 compression support is experimental\n");
2019 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002020
2021 /* Numeric Values */
2022 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002023 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002024 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
2025 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05002026 goto cifs_parse_mount_err;
2027 }
2028 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002029 break;
2030 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002031 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002032 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
2033 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05002034 goto cifs_parse_mount_err;
2035 }
2036 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002037 break;
2038 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002039 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002040 cifs_dbg(VFS, "%s: Invalid uid value\n",
2041 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00002042 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002044 uid_specified = true;
2045 break;
2046 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002047 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002048 cifs_dbg(VFS, "%s: Invalid cruid value\n",
2049 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002050 goto cifs_parse_mount_err;
2051 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002052 break;
2053 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002054 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002055 cifs_dbg(VFS, "%s: Invalid gid value\n",
2056 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002057 goto cifs_parse_mount_err;
2058 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002059 gid_specified = true;
2060 break;
2061 case Opt_file_mode:
2062 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002063 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
2064 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002065 goto cifs_parse_mount_err;
2066 }
2067 vol->file_mode = option;
2068 break;
2069 case Opt_dirmode:
2070 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002071 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
2072 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002073 goto cifs_parse_mount_err;
2074 }
2075 vol->dir_mode = option;
2076 break;
2077 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002078 if (get_option_ul(args, &option) ||
2079 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002080 cifs_dbg(VFS, "%s: Invalid port value\n",
2081 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002082 goto cifs_parse_mount_err;
2083 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002084 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002085 break;
Steve French563317e2019-09-08 23:22:02 -05002086 case Opt_min_enc_offload:
2087 if (get_option_ul(args, &option)) {
2088 cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
2089 goto cifs_parse_mount_err;
2090 }
2091 vol->min_offload = option;
2092 break;
Steve Frenche8506d22019-02-28 21:32:15 -06002093 case Opt_blocksize:
2094 if (get_option_ul(args, &option)) {
2095 cifs_dbg(VFS, "%s: Invalid blocksize value\n",
2096 __func__);
2097 goto cifs_parse_mount_err;
2098 }
2099 /*
2100 * inode blocksize realistically should never need to be
2101 * less than 16K or greater than 16M and default is 1MB.
2102 * Note that small inode block sizes (e.g. 64K) can lead
2103 * to very poor performance of common tools like cp and scp
2104 */
2105 if ((option < CIFS_MAX_MSGSIZE) ||
2106 (option > (4 * SMB3_DEFAULT_IOSIZE))) {
2107 cifs_dbg(VFS, "%s: Invalid blocksize\n",
2108 __func__);
2109 goto cifs_parse_mount_err;
2110 }
2111 vol->bsize = option;
2112 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002113 case Opt_rsize:
2114 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002115 cifs_dbg(VFS, "%s: Invalid rsize value\n",
2116 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002117 goto cifs_parse_mount_err;
2118 }
2119 vol->rsize = option;
2120 break;
2121 case Opt_wsize:
2122 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002123 cifs_dbg(VFS, "%s: Invalid wsize value\n",
2124 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002125 goto cifs_parse_mount_err;
2126 }
2127 vol->wsize = option;
2128 break;
2129 case Opt_actimeo:
2130 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002131 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
2132 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002133 goto cifs_parse_mount_err;
2134 }
2135 vol->actimeo = HZ * option;
2136 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002137 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002138 goto cifs_parse_mount_err;
2139 }
2140 break;
Steve Frenchca567eb2019-03-29 16:31:07 -05002141 case Opt_handletimeout:
2142 if (get_option_ul(args, &option)) {
2143 cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
2144 __func__);
2145 goto cifs_parse_mount_err;
2146 }
2147 vol->handle_timeout = option;
2148 if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
2149 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
2150 goto cifs_parse_mount_err;
2151 }
2152 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002153 case Opt_echo_interval:
2154 if (get_option_ul(args, &option)) {
2155 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
2156 __func__);
2157 goto cifs_parse_mount_err;
2158 }
2159 vol->echo_interval = option;
2160 break;
Steve French8b217fe2016-11-11 22:36:20 -06002161 case Opt_snapshot:
2162 if (get_option_ul(args, &option)) {
2163 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
2164 __func__);
2165 goto cifs_parse_mount_err;
2166 }
2167 vol->snapshot_time = option;
2168 break;
Steve French141891f2016-09-23 00:44:16 -05002169 case Opt_max_credits:
2170 if (get_option_ul(args, &option) || (option < 20) ||
2171 (option > 60000)) {
2172 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
2173 __func__);
2174 goto cifs_parse_mount_err;
2175 }
2176 vol->max_credits = option;
2177 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002178 case Opt_max_channels:
2179 if (get_option_ul(args, &option) || option < 1 ||
2180 option > CIFS_MAX_CHANNELS) {
2181 cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
2182 __func__, CIFS_MAX_CHANNELS);
2183 goto cifs_parse_mount_err;
2184 }
2185 vol->max_channels = option;
2186 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002187
2188 /* String Arguments */
2189
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002190 case Opt_blank_user:
2191 /* null user, ie. anonymous authentication */
2192 vol->nullauth = 1;
2193 vol->username = NULL;
2194 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002195 case Opt_user:
2196 string = match_strdup(args);
2197 if (string == NULL)
2198 goto out_nomem;
2199
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002200 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
2201 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002202 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002203 goto cifs_parse_mount_err;
2204 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002205
2206 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002207 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05002208 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002209 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002210 break;
2211 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002212 /* passwords have to be handled differently
2213 * to allow the character used for deliminator
2214 * to be passed within them
2215 */
2216
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002217 /*
2218 * Check if this is a case where the password
2219 * starts with a delimiter
2220 */
2221 tmp_end = strchr(data, '=');
2222 tmp_end++;
2223 if (!(tmp_end < end && tmp_end[1] == delim)) {
2224 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002225 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002226 vol->password = NULL;
2227 break;
2228 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +11002229 /* Fallthrough - to Opt_pass below.*/
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002230 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002231 /* Obtain the value string */
2232 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002233 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002234
2235 /* Set tmp_end to end of the string */
2236 tmp_end = (char *) value + strlen(value);
2237
2238 /* Check if following character is the deliminator
2239 * If yes, we have encountered a double deliminator
2240 * reset the NULL character to the deliminator
2241 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302242 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002243 tmp_end[0] = delim;
2244
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302245 /* Keep iterating until we get to a single
2246 * deliminator OR the end
2247 */
2248 while ((tmp_end = strchr(tmp_end, delim))
2249 != NULL && (tmp_end[1] == delim)) {
2250 tmp_end = (char *) &tmp_end[2];
2251 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002252
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302253 /* Reset var options to point to next element */
2254 if (tmp_end) {
2255 tmp_end[0] = '\0';
2256 options = (char *) &tmp_end[1];
2257 } else
2258 /* Reached the end of the mount option
2259 * string */
2260 options = end;
2261 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002262
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002263 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002264 /* Now build new password string */
2265 temp_len = strlen(value);
2266 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2267 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002268 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002269 goto cifs_parse_mount_err;
2270 }
2271
2272 for (i = 0, j = 0; i < temp_len; i++, j++) {
2273 vol->password[j] = value[i];
2274 if ((value[i] == delim) &&
2275 value[i+1] == delim)
2276 /* skip the second deliminator */
2277 i++;
2278 }
2279 vol->password[j] = '\0';
2280 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002281 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002282 /* FIXME: should this be an error instead? */
2283 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002284 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002285 case Opt_ip:
2286 string = match_strdup(args);
2287 if (string == NULL)
2288 goto out_nomem;
2289
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002290 if (!cifs_convert_address(dstaddr, string,
2291 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002292 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002293 goto cifs_parse_mount_err;
2294 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002295 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002296 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002297 case Opt_domain:
2298 string = match_strdup(args);
2299 if (string == NULL)
2300 goto out_nomem;
2301
Chen Gang057d6332013-07-19 09:01:36 +08002302 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2303 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002304 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002305 goto cifs_parse_mount_err;
2306 }
2307
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002308 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002309 vol->domainname = kstrdup(string, GFP_KERNEL);
2310 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002311 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002312 goto cifs_parse_mount_err;
2313 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002314 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002315 break;
2316 case Opt_srcaddr:
2317 string = match_strdup(args);
2318 if (string == NULL)
2319 goto out_nomem;
2320
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002321 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002322 (struct sockaddr *)&vol->srcaddr,
2323 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002324 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2325 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002326 goto cifs_parse_mount_err;
2327 }
2328 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002329 case Opt_iocharset:
2330 string = match_strdup(args);
2331 if (string == NULL)
2332 goto out_nomem;
2333
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002334 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002335 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002336 goto cifs_parse_mount_err;
2337 }
2338
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002339 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002340 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002341 vol->iocharset = kstrdup(string,
2342 GFP_KERNEL);
2343 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002344 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002345 goto cifs_parse_mount_err;
2346 }
2347 }
2348 /* if iocharset not set then load_nls_default
2349 * is used by caller
2350 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002351 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002352 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002353 case Opt_netbiosname:
2354 string = match_strdup(args);
2355 if (string == NULL)
2356 goto out_nomem;
2357
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002358 memset(vol->source_rfc1001_name, 0x20,
2359 RFC1001_NAME_LEN);
2360 /*
2361 * FIXME: are there cases in which a comma can
2362 * be valid in workstation netbios name (and
2363 * need special handling)?
2364 */
2365 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2366 /* don't ucase netbiosname for user */
2367 if (string[i] == 0)
2368 break;
2369 vol->source_rfc1001_name[i] = string[i];
2370 }
2371 /* The string has 16th byte zero still from
2372 * set at top of the function
2373 */
2374 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002375 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002376 break;
2377 case Opt_servern:
2378 /* servernetbiosname specified override *SMBSERVER */
2379 string = match_strdup(args);
2380 if (string == NULL)
2381 goto out_nomem;
2382
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002383 /* last byte, type, is 0x20 for servr type */
2384 memset(vol->target_rfc1001_name, 0x20,
2385 RFC1001_NAME_LEN_WITH_NULL);
2386
2387 /* BB are there cases in which a comma can be
2388 valid in this workstation netbios name
2389 (and need special handling)? */
2390
2391 /* user or mount helper must uppercase the
2392 netbios name */
2393 for (i = 0; i < 15; i++) {
2394 if (string[i] == 0)
2395 break;
2396 vol->target_rfc1001_name[i] = string[i];
2397 }
2398 /* The string has 16th byte zero still from
2399 set at top of the function */
2400 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002401 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002402 break;
2403 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002404 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002405 string = match_strdup(args);
2406 if (string == NULL)
2407 goto out_nomem;
2408
Steve French7e682f72017-08-31 21:34:24 -05002409 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002410 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002411 if (strlen(string) > 1) {
2412 pr_warn("Bad mount helper ver=%s. Did "
2413 "you want SMB1 (CIFS) dialect "
2414 "and mean to type vers=1.0 "
2415 "instead?\n", string);
2416 goto cifs_parse_mount_err;
2417 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002418 /* This is the default */
2419 break;
2420 }
2421 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05002422 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002423 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002424 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002425 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002426 string = match_strdup(args);
2427 if (string == NULL)
2428 goto out_nomem;
2429
Steve Frenchc7c137b2018-06-06 17:59:29 -05002430 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002431 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002432 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002433 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002434 case Opt_sec:
2435 string = match_strdup(args);
2436 if (string == NULL)
2437 goto out_nomem;
2438
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002439 if (cifs_parse_security_flavors(string, vol) != 0)
2440 goto cifs_parse_mount_err;
2441 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002442 case Opt_cache:
2443 string = match_strdup(args);
2444 if (string == NULL)
2445 goto out_nomem;
2446
2447 if (cifs_parse_cache_flavor(string, vol) != 0)
2448 goto cifs_parse_mount_err;
2449 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002450 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002451 /*
2452 * An option we don't recognize. Save it off for later
2453 * if we haven't already found one
2454 */
2455 if (!invalid)
2456 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002457 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002459 /* Free up any allocated string */
2460 kfree(string);
2461 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002463
Jeff Laytond8162552012-03-23 14:40:56 -04002464 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002465 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002466 goto cifs_parse_mount_err;
2467 }
2468
Long Li8339dd32017-11-07 01:54:55 -07002469 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2470 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2471 goto cifs_parse_mount_err;
2472 }
2473
Jeff Layton8a8798a2012-01-17 16:09:15 -05002474#ifndef CONFIG_KEYS
2475 /* Muliuser mounts require CONFIG_KEYS support */
2476 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002477 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002478 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002479 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002480#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002481 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002482 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002483 goto cifs_parse_mount_err;
2484 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002485
Jeff Layton62a1a432012-12-10 06:10:45 -05002486 /* make sure UNC has a share name */
2487 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002488 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002489 goto cifs_parse_mount_err;
2490 }
2491
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002492 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002493 int len;
2494 const char *slash;
2495
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002496 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002497 /* Use the address part of the UNC. */
2498 slash = strchr(&vol->UNC[2], '\\');
2499 len = slash - &vol->UNC[2];
2500 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002501 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002502 goto cifs_parse_mount_err;
2503 }
2504 }
2505
2506 /* set the port that we got earlier */
2507 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002509 if (uid_specified)
2510 vol->override_uid = override_uid;
2511 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002512 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002513
2514 if (gid_specified)
2515 vol->override_gid = override_gid;
2516 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002517 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002518
Steve French7e682f72017-08-31 21:34:24 -05002519 if (got_version == false)
2520 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002521 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002522 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002523 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2524 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002525
Sean Finneyb9468452011-04-11 13:19:32 +00002526 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002528
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002529out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002530 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002531cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002532 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002533 kfree(mountdata_copy);
2534 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535}
2536
Ben Greear3eb9a882010-09-01 17:06:02 -07002537/** Returns true if srcaddr isn't specified and rhs isn't
2538 * specified, or if srcaddr is specified and
2539 * matches the IP address of the rhs argument.
2540 */
Jeff Layton45151482010-07-06 20:43:02 -04002541static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002542srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2543{
2544 switch (srcaddr->sa_family) {
2545 case AF_UNSPEC:
2546 return (rhs->sa_family == AF_UNSPEC);
2547 case AF_INET: {
2548 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2549 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2550 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2551 }
2552 case AF_INET6: {
2553 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002554 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002555 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2556 }
2557 default:
2558 WARN_ON(1);
2559 return false; /* don't expect to be here */
2560 }
2561}
2562
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002563/*
2564 * If no port is specified in addr structure, we try to match with 445 port
2565 * and if it fails - with 139 ports. It should be called only if address
2566 * families of server and addr are equal.
2567 */
2568static bool
2569match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2570{
Steve French6da97912011-03-13 18:55:55 +00002571 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002572
Long Li3b249112019-05-15 14:09:04 -07002573 /* SMBDirect manages its own ports, don't match it here */
2574 if (server->rdma)
2575 return true;
2576
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002577 switch (addr->sa_family) {
2578 case AF_INET:
2579 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2580 port = ((struct sockaddr_in *) addr)->sin_port;
2581 break;
2582 case AF_INET6:
2583 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2584 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2585 break;
2586 default:
2587 WARN_ON(1);
2588 return false;
2589 }
2590
2591 if (!port) {
2592 port = htons(CIFS_PORT);
2593 if (port == *sport)
2594 return true;
2595
2596 port = htons(RFC1001_PORT);
2597 }
2598
2599 return port == *sport;
2600}
Ben Greear3eb9a882010-09-01 17:06:02 -07002601
2602static bool
2603match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2604 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605{
Jeff Layton45151482010-07-06 20:43:02 -04002606 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002607 case AF_INET: {
2608 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2609 struct sockaddr_in *srv_addr4 =
2610 (struct sockaddr_in *)&server->dstaddr;
2611
2612 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002613 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002614 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002615 }
2616 case AF_INET6: {
2617 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2618 struct sockaddr_in6 *srv_addr6 =
2619 (struct sockaddr_in6 *)&server->dstaddr;
2620
Jeff Layton45151482010-07-06 20:43:02 -04002621 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002622 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002623 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002624 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002625 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002626 break;
2627 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002628 default:
2629 WARN_ON(1);
2630 return false; /* don't expect to be here */
2631 }
Jeff Layton45151482010-07-06 20:43:02 -04002632
Ben Greear3eb9a882010-09-01 17:06:02 -07002633 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2634 return false;
2635
Jeff Layton45151482010-07-06 20:43:02 -04002636 return true;
2637}
2638
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002639static bool
2640match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2641{
Jeff Layton3f618222013-06-12 19:52:14 -05002642 /*
2643 * The select_sectype function should either return the vol->sectype
2644 * that was specified, or "Unspecified" if that sectype was not
2645 * compatible with the given NEGOTIATE request.
2646 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302647 if (server->ops->select_sectype(server, vol->sectype)
2648 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002649 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002650
Jeff Layton3f618222013-06-12 19:52:14 -05002651 /*
2652 * Now check if signing mode is acceptable. No need to check
2653 * global_secflags at this point since if MUST_SIGN is set then
2654 * the server->sign had better be too.
2655 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002656 if (vol->sign && !server->sign)
2657 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002658
2659 return true;
2660}
2661
Jeff Layton9fa114f2012-11-26 11:09:57 -05002662static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002663{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002664 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2665
Jeff Laytona0b3df52013-05-24 07:40:59 -04002666 if (vol->nosharesock)
2667 return 0;
2668
Steve French43cdae82019-06-13 14:26:49 -05002669 /* If multidialect negotiation see if existing sessions match one */
2670 if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2671 if (server->vals->protocol_id < SMB30_PROT_ID)
2672 return 0;
2673 } else if (strcmp(vol->vals->version_string,
2674 SMBDEFAULT_VERSION_STRING) == 0) {
2675 if (server->vals->protocol_id < SMB21_PROT_ID)
2676 return 0;
2677 } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
Jeff Layton23db65f2012-05-15 12:20:51 -04002678 return 0;
2679
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002680 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2681 return 0;
2682
2683 if (!match_address(server, addr,
2684 (struct sockaddr *)&vol->srcaddr))
2685 return 0;
2686
2687 if (!match_port(server, addr))
2688 return 0;
2689
2690 if (!match_security(server, vol))
2691 return 0;
2692
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002693 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002694 return 0;
2695
Long Li8339dd32017-11-07 01:54:55 -07002696 if (server->rdma != vol->rdma)
2697 return 0;
2698
Steve French4f5c10f2019-09-03 21:18:49 -05002699 if (server->ignore_signature != vol->ignore_signature)
2700 return 0;
2701
Steve French563317e2019-09-08 23:22:02 -05002702 if (server->min_offload != vol->min_offload)
2703 return 0;
2704
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002705 return 1;
2706}
2707
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002708struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002709cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002710{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002711 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302713 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002714 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Paulo Alcantara (SUSE)3345bb42019-12-04 11:25:06 -03002715 /*
2716 * Skip ses channels since they're only handled in lower layers
2717 * (e.g. cifs_send_recv).
2718 */
2719 if (server->is_channel || !match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002720 continue;
2721
Jeff Laytone7ddee92008-11-14 13:44:38 -05002722 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302723 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002724 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002725 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302727 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 return NULL;
2729}
2730
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002731void
2732cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002734 struct task_struct *task;
2735
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302736 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002737 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302738 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002739 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002741
Rob Landleyf1d0c992011-01-22 15:44:05 -06002742 put_net(cifs_net_ns(server));
2743
Jeff Laytone7ddee92008-11-14 13:44:38 -05002744 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302745 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002746
Jeff Laytonc74093b2011-01-11 07:24:23 -05002747 cancel_delayed_work_sync(&server->echo);
2748
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002749 if (from_reconnect)
2750 /*
2751 * Avoid deadlock here: reconnect work calls
2752 * cifs_put_tcp_session() at its end. Need to be sure
2753 * that reconnect work does nothing with server pointer after
2754 * that step.
2755 */
2756 cancel_delayed_work(&server->reconnect);
2757 else
2758 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002759
Jeff Laytone7ddee92008-11-14 13:44:38 -05002760 spin_lock(&GlobalMid_Lock);
2761 server->tcpStatus = CifsExiting;
2762 spin_unlock(&GlobalMid_Lock);
2763
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002764 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302765 cifs_fscache_release_client_cookie(server);
2766
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002767 kfree(server->session_key.response);
2768 server->session_key.response = NULL;
2769 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002770
2771 task = xchg(&server->tsk, NULL);
2772 if (task)
Eric W. Biederman72abe3b2019-05-15 12:33:50 -05002773 send_sig(SIGKILL, task, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774}
2775
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02002776struct TCP_Server_Info *
Jeff Layton63c038c2008-12-01 18:41:46 -05002777cifs_get_tcp_session(struct smb_vol *volume_info)
2778{
2779 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002780 int rc;
2781
Joe Perchesf96637b2013-05-04 22:12:25 -05002782 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002783
2784 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002785 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002786 if (tcp_ses)
2787 return tcp_ses;
2788
2789 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2790 if (!tcp_ses) {
2791 rc = -ENOMEM;
2792 goto out_err;
2793 }
2794
Jeff Layton23db65f2012-05-15 12:20:51 -04002795 tcp_ses->ops = volume_info->ops;
2796 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002797 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002798 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2799 if (IS_ERR(tcp_ses->hostname)) {
2800 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002801 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002802 }
2803
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03002804 tcp_ses->noblockcnt = volume_info->rootfs;
2805 tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
Jeff Layton63c038c2008-12-01 18:41:46 -05002806 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002807 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002808 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002809 tcp_ses->in_flight = 0;
Steve French1b63f182019-09-09 22:57:11 -05002810 tcp_ses->max_in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002811 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002812 init_waitqueue_head(&tcp_ses->response_q);
2813 init_waitqueue_head(&tcp_ses->request_q);
2814 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2815 mutex_init(&tcp_ses->srv_mutex);
2816 memcpy(tcp_ses->workstation_RFC1001_name,
2817 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2818 memcpy(tcp_ses->server_RFC1001_name,
2819 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002820 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002821 tcp_ses->sequence_number = 0;
Pavel Shilovsky5b964852019-01-18 11:30:26 -08002822 tcp_ses->reconnect_instance = 1;
Steve Frenchfda35942011-01-20 18:06:34 +00002823 tcp_ses->lstrp = jiffies;
Steve French9fe5ff12019-06-24 20:39:04 -05002824 tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
Jeff Layton58fa0152012-05-01 17:41:16 -04002825 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002826 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2827 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002828 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002829 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2830 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002831 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2832 sizeof(tcp_ses->srcaddr));
2833 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2834 sizeof(tcp_ses->dstaddr));
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002835 if (volume_info->use_client_guid)
2836 memcpy(tcp_ses->client_guid, volume_info->client_guid,
2837 SMB2_CLIENT_GUID_SIZE);
2838 else
2839 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002840 /*
2841 * at this point we are the only ones with the pointer
2842 * to the struct since the kernel thread not created yet
2843 * no need to spinlock this init of tcpStatus or srv_count
2844 */
2845 tcp_ses->tcpStatus = CifsNew;
2846 ++tcp_ses->srv_count;
2847
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002848 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2849 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2850 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2851 else
2852 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002853 if (tcp_ses->rdma) {
2854#ifndef CONFIG_CIFS_SMB_DIRECT
2855 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2856 rc = -ENOENT;
2857 goto out_err_crypto_release;
2858#endif
2859 tcp_ses->smbd_conn = smbd_get_connection(
2860 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2861 if (tcp_ses->smbd_conn) {
2862 cifs_dbg(VFS, "RDMA transport established\n");
2863 rc = 0;
2864 goto smbd_connected;
2865 } else {
2866 rc = -ENOENT;
2867 goto out_err_crypto_release;
2868 }
2869 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002870 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002871 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002872 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002873 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002874 }
Long Li2f894642017-11-22 17:38:34 -07002875smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002876 /*
2877 * since we're in a cifs function already, we know that
2878 * this will succeed. No need for try_module_get().
2879 */
2880 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002881 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002882 tcp_ses, "cifsd");
2883 if (IS_ERR(tcp_ses->tsk)) {
2884 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002885 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002886 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002887 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002888 }
Steve French563317e2019-09-08 23:22:02 -05002889 tcp_ses->min_offload = volume_info->min_offload;
Steve Frenchfd88ce92011-04-12 01:01:14 +00002890 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002891
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002892 tcp_ses->nr_targets = 1;
Steve French4f5c10f2019-09-03 21:18:49 -05002893 tcp_ses->ignore_signature = volume_info->ignore_signature;
Jeff Layton63c038c2008-12-01 18:41:46 -05002894 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302895 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002896 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302897 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002898
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302899 cifs_fscache_get_client_cookie(tcp_ses);
2900
Jeff Laytonc74093b2011-01-11 07:24:23 -05002901 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002902 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002903
Jeff Layton63c038c2008-12-01 18:41:46 -05002904 return tcp_ses;
2905
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002906out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002907 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002908
Rob Landleyf1d0c992011-01-22 15:44:05 -06002909 put_net(cifs_net_ns(tcp_ses));
2910
Jeff Layton63c038c2008-12-01 18:41:46 -05002911out_err:
2912 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002913 if (!IS_ERR(tcp_ses->hostname))
2914 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002915 if (tcp_ses->ssocket)
2916 sock_release(tcp_ses->ssocket);
2917 kfree(tcp_ses);
2918 }
2919 return ERR_PTR(rc);
2920}
2921
Steve French96daf2b2011-05-27 04:34:02 +00002922static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002923{
Jeff Layton3f618222013-06-12 19:52:14 -05002924 if (vol->sectype != Unspecified &&
2925 vol->sectype != ses->sectype)
2926 return 0;
2927
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002928 /*
2929 * If an existing session is limited to less channels than
2930 * requested, it should not be reused
2931 */
2932 if (ses->chan_max < vol->max_channels)
2933 return 0;
2934
Jeff Layton3f618222013-06-12 19:52:14 -05002935 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002936 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002937 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002938 return 0;
2939 break;
2940 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002941 /* NULL username means anonymous session */
2942 if (ses->user_name == NULL) {
2943 if (!vol->nullauth)
2944 return 0;
2945 break;
2946 }
2947
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002948 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002949 if (strncmp(ses->user_name,
2950 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002951 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002952 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002953 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002954 ses->password != NULL &&
2955 strncmp(ses->password,
2956 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002957 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002958 return 0;
2959 }
2960 return 1;
2961}
2962
Aurelien Aptelb327a712018-01-24 13:46:10 +01002963/**
2964 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2965 *
2966 * A new IPC connection is made and stored in the session
2967 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2968 */
2969static int
2970cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2971{
2972 int rc = 0, xid;
2973 struct cifs_tcon *tcon;
2974 struct nls_table *nls_codepage;
2975 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2976 bool seal = false;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002977 struct TCP_Server_Info *server = ses->server;
Aurelien Aptelb327a712018-01-24 13:46:10 +01002978
2979 /*
2980 * If the mount request that resulted in the creation of the
2981 * session requires encryption, force IPC to be encrypted too.
2982 */
2983 if (volume_info->seal) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002984 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
Aurelien Aptelb327a712018-01-24 13:46:10 +01002985 seal = true;
2986 else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002987 cifs_server_dbg(VFS,
Aurelien Aptelb327a712018-01-24 13:46:10 +01002988 "IPC: server doesn't support encryption\n");
2989 return -EOPNOTSUPP;
2990 }
2991 }
2992
2993 tcon = tconInfoAlloc();
2994 if (tcon == NULL)
2995 return -ENOMEM;
2996
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002997 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002998
2999 /* cannot fail */
3000 nls_codepage = load_nls_default();
3001
3002 xid = get_xid();
3003 tcon->ses = ses;
3004 tcon->ipc = true;
3005 tcon->seal = seal;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003006 rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003007 free_xid(xid);
3008
3009 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003010 cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003011 tconInfoFree(tcon);
3012 goto out;
3013 }
3014
3015 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
3016
3017 ses->tcon_ipc = tcon;
3018out:
3019 unload_nls(nls_codepage);
3020 return rc;
3021}
3022
3023/**
3024 * cifs_free_ipc - helper to release the session IPC tcon
3025 *
3026 * Needs to be called everytime a session is destroyed
3027 */
3028static int
3029cifs_free_ipc(struct cifs_ses *ses)
3030{
3031 int rc = 0, xid;
3032 struct cifs_tcon *tcon = ses->tcon_ipc;
3033
3034 if (tcon == NULL)
3035 return 0;
3036
3037 if (ses->server->ops->tree_disconnect) {
3038 xid = get_xid();
3039 rc = ses->server->ops->tree_disconnect(xid, tcon);
3040 free_xid(xid);
3041 }
3042
3043 if (rc)
3044 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
3045
3046 tconInfoFree(tcon);
3047 ses->tcon_ipc = NULL;
3048 return rc;
3049}
3050
Steve French96daf2b2011-05-27 04:34:02 +00003051static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04003052cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053{
Steve French96daf2b2011-05-27 04:34:02 +00003054 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303056 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04003057 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003058 if (ses->status == CifsExiting)
3059 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003060 if (!match_session(ses, vol))
3061 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05003062 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303063 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003064 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303066 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067 return NULL;
3068}
3069
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003070void cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05003071{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003072 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05003073 struct TCP_Server_Info *server = ses->server;
3074
Joe Perchesf96637b2013-05-04 22:12:25 -05003075 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003076
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303077 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003078 if (ses->status == CifsExiting) {
3079 spin_unlock(&cifs_tcp_ses_lock);
3080 return;
3081 }
Jeff Layton14fbf502008-11-14 13:53:46 -05003082 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303083 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003084 return;
3085 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003086 if (ses->status == CifsGood)
3087 ses->status = CifsExiting;
3088 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003089
Aurelien Aptelb327a712018-01-24 13:46:10 +01003090 cifs_free_ipc(ses);
3091
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003092 if (ses->status == CifsExiting && server->ops->logoff) {
3093 xid = get_xid();
3094 rc = server->ops->logoff(xid, ses);
3095 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003096 cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003097 __func__, rc);
3098 _free_xid(xid);
3099 }
3100
3101 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003102 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303103 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003104
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003105 /* close any extra channels */
3106 if (ses->chan_count > 1) {
3107 int i;
3108
3109 for (i = 1; i < ses->chan_count; i++)
3110 cifs_put_tcp_session(ses->chans[i].server, 0);
3111 }
3112
Jeff Layton14fbf502008-11-14 13:53:46 -05003113 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003114 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05003115}
3116
Jeff Layton8a8798a2012-01-17 16:09:15 -05003117#ifdef CONFIG_KEYS
3118
Chen Gang057d6332013-07-19 09:01:36 +08003119/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
3120#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05003121
3122/* Populate username and pw fields from keyring if possible */
3123static int
3124cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
3125{
3126 int rc = 0;
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003127 int is_domain = 0;
David Howells146aa8b2015-10-21 14:04:48 +01003128 const char *delim, *payload;
3129 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003130 ssize_t len;
3131 struct key *key;
3132 struct TCP_Server_Info *server = ses->server;
3133 struct sockaddr_in *sa;
3134 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01003135 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003136
3137 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
3138 if (!desc)
3139 return -ENOMEM;
3140
3141 /* try to find an address key first */
3142 switch (server->dstaddr.ss_family) {
3143 case AF_INET:
3144 sa = (struct sockaddr_in *)&server->dstaddr;
3145 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
3146 break;
3147 case AF_INET6:
3148 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
3149 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
3150 break;
3151 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05003152 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
3153 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003154 rc = -EINVAL;
3155 goto out_err;
3156 }
3157
Joe Perchesf96637b2013-05-04 22:12:25 -05003158 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003159 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003160 if (IS_ERR(key)) {
3161 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003162 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003163 rc = PTR_ERR(key);
3164 goto out_err;
3165 }
3166
3167 /* didn't work, try to find a domain key */
3168 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05003169 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003170 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003171 if (IS_ERR(key)) {
3172 rc = PTR_ERR(key);
3173 goto out_err;
3174 }
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003175 is_domain = 1;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003176 }
3177
3178 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00003179 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003180 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05003181 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003182 goto out_key_put;
3183 }
3184
3185 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01003186 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003187 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05003188 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003189 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003190 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
3191 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003192 rc = -EINVAL;
3193 goto out_key_put;
3194 }
3195
3196 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003197 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003198 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
3199 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003200 rc = -EINVAL;
3201 goto out_key_put;
3202 }
3203
3204 vol->username = kstrndup(payload, len, GFP_KERNEL);
3205 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003206 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
3207 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003208 rc = -ENOMEM;
3209 goto out_key_put;
3210 }
Joe Perchesf96637b2013-05-04 22:12:25 -05003211 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003212
3213 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003214 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003215 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003216 rc = -EINVAL;
3217 kfree(vol->username);
3218 vol->username = NULL;
3219 goto out_key_put;
3220 }
3221
3222 ++delim;
3223 vol->password = kstrndup(delim, len, GFP_KERNEL);
3224 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003225 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
3226 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003227 rc = -ENOMEM;
3228 kfree(vol->username);
3229 vol->username = NULL;
3230 goto out_key_put;
3231 }
3232
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003233 /*
3234 * If we have a domain key then we must set the domainName in the
3235 * for the request.
3236 */
3237 if (is_domain && ses->domainName) {
3238 vol->domainname = kstrndup(ses->domainName,
3239 strlen(ses->domainName),
3240 GFP_KERNEL);
3241 if (!vol->domainname) {
3242 cifs_dbg(FYI, "Unable to allocate %zd bytes for "
3243 "domain\n", len);
3244 rc = -ENOMEM;
3245 kfree(vol->username);
3246 vol->username = NULL;
Dan Carpenter478228e2019-08-27 13:59:17 +03003247 kzfree(vol->password);
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003248 vol->password = NULL;
3249 goto out_key_put;
3250 }
3251 }
3252
Jeff Layton8a8798a2012-01-17 16:09:15 -05003253out_key_put:
3254 up_read(&key->sem);
3255 key_put(key);
3256out_err:
3257 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05003258 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003259 return rc;
3260}
3261#else /* ! CONFIG_KEYS */
3262static inline int
3263cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
3264 struct cifs_ses *ses __attribute__((unused)))
3265{
3266 return -ENOSYS;
3267}
3268#endif /* CONFIG_KEYS */
3269
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003270/**
3271 * cifs_get_smb_ses - get a session matching @volume_info data from @server
3272 *
3273 * This function assumes it is being called from cifs_mount() where we
3274 * already got a server reference (server refcount +1). See
3275 * cifs_get_tcon() for refcount explanations.
3276 */
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003277struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04003278cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3279{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003280 int rc = -ENOMEM;
3281 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003282 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003283 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3284 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04003285
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003286 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04003287
Jeff Layton4ff67b72010-07-06 20:43:02 -04003288 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04003289 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003290 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3291 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04003292
Jeff Layton36988c72010-04-24 07:57:43 -04003293 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003294 rc = cifs_negotiate_protocol(xid, ses);
3295 if (rc) {
3296 mutex_unlock(&ses->session_mutex);
3297 /* problem -- put our ses reference */
3298 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003299 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003300 return ERR_PTR(rc);
3301 }
Jeff Layton36988c72010-04-24 07:57:43 -04003302 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003303 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003304 rc = cifs_setup_session(xid, ses,
3305 volume_info->local_nls);
3306 if (rc) {
3307 mutex_unlock(&ses->session_mutex);
3308 /* problem -- put our reference */
3309 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003310 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003311 return ERR_PTR(rc);
3312 }
3313 }
3314 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003315
3316 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003317 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003318 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003319 return ses;
3320 }
3321
Joe Perchesf96637b2013-05-04 22:12:25 -05003322 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003323 ses = sesInfoAlloc();
3324 if (ses == NULL)
3325 goto get_ses_fail;
3326
3327 /* new SMB session uses our server ref */
3328 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003329 if (server->dstaddr.ss_family == AF_INET6)
3330 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003331 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003332 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003333
Steve French8727c8a2011-02-25 01:11:56 -06003334 if (volume_info->username) {
3335 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3336 if (!ses->user_name)
3337 goto get_ses_fail;
3338 }
Jeff Layton36988c72010-04-24 07:57:43 -04003339
3340 /* volume_info->password freed at unmount */
3341 if (volume_info->password) {
3342 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3343 if (!ses->password)
3344 goto get_ses_fail;
3345 }
3346 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003347 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3348 if (!ses->domainName)
3349 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003350 }
Germano Percossi39566442016-12-15 12:31:18 +05303351 if (volume_info->domainauto)
3352 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003353 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003354 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003355
Jeff Layton28e11bd2013-05-26 07:01:00 -04003356 ses->sectype = volume_info->sectype;
3357 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003358 mutex_lock(&ses->session_mutex);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003359
3360 /* add server as first channel */
3361 ses->chans[0].server = server;
3362 ses->chan_count = 1;
3363 ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1;
3364
Jeff Layton198b5682010-04-24 07:57:48 -04003365 rc = cifs_negotiate_protocol(xid, ses);
3366 if (!rc)
3367 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003368
3369 /* each channel uses a different signing key */
3370 memcpy(ses->chans[0].signkey, ses->smb3signingkey,
3371 sizeof(ses->smb3signingkey));
3372
Jeff Layton36988c72010-04-24 07:57:43 -04003373 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003374 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003375 goto get_ses_fail;
3376
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003377 /* success, put it on the list and add it as first channel */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303378 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003379 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303380 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003381
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003382 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003383
3384 cifs_setup_ipc(ses, volume_info);
3385
Jeff Layton36988c72010-04-24 07:57:43 -04003386 return ses;
3387
3388get_ses_fail:
3389 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003390 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003391 return ERR_PTR(rc);
3392}
3393
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003394static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003395{
3396 if (tcon->tidStatus == CifsExiting)
3397 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003398 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003399 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003400 if (tcon->seal != volume_info->seal)
3401 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003402 if (tcon->snapshot_time != volume_info->snapshot_time)
3403 return 0;
Steve Frenchca567eb2019-03-29 16:31:07 -05003404 if (tcon->handle_timeout != volume_info->handle_timeout)
3405 return 0;
Steve French3e7a02d2019-09-11 21:46:20 -05003406 if (tcon->no_lease != volume_info->no_lease)
3407 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003408 return 1;
3409}
3410
Steve French96daf2b2011-05-27 04:34:02 +00003411static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003412cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413{
3414 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003415 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303417 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003418 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003419 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003420 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003421 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003422 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303423 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424 return tcon;
3425 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303426 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 return NULL;
3428}
3429
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003430void
Steve French96daf2b2011-05-27 04:34:02 +00003431cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003432{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003433 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003434 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003435
Aurelien Aptelb327a712018-01-24 13:46:10 +01003436 /*
3437 * IPC tcon share the lifetime of their session and are
3438 * destroyed in the session put function
3439 */
3440 if (tcon == NULL || tcon->ipc)
3441 return;
3442
3443 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003444 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303445 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003446 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303447 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003448 return;
3449 }
3450
3451 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303452 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003453
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003454 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003455 if (ses->server->ops->tree_disconnect)
3456 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003457 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003458
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303459 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003460 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003461 cifs_put_smb_ses(ses);
3462}
3463
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003464/**
3465 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3466 *
3467 * - tcon refcount is the number of mount points using the tcon.
3468 * - ses refcount is the number of tcon using the session.
3469 *
3470 * 1. This function assumes it is being called from cifs_mount() where
3471 * we already got a session reference (ses refcount +1).
3472 *
3473 * 2. Since we're in the context of adding a mount point, the end
3474 * result should be either:
3475 *
3476 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3477 * its session refcount incremented (1 new tcon). This +1 was
3478 * already done in (1).
3479 *
3480 * b) an existing tcon with refcount+1 (add a mount point to it) and
3481 * identical ses refcount (no new tcon). Because of (1) we need to
3482 * decrement the ses refcount.
3483 */
Steve French96daf2b2011-05-27 04:34:02 +00003484static struct cifs_tcon *
3485cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003486{
3487 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003488 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003489
Steve French8b217fe2016-11-11 22:36:20 -06003490 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003491 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003492 /*
3493 * tcon has refcount already incremented but we need to
3494 * decrement extra ses reference gotten by caller (case b)
3495 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003496 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003497 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003498 return tcon;
3499 }
3500
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003501 if (!ses->server->ops->tree_connect) {
3502 rc = -ENOSYS;
3503 goto out_fail;
3504 }
3505
Jeff Laytond00c28d2010-04-24 07:57:44 -04003506 tcon = tconInfoAlloc();
3507 if (tcon == NULL) {
3508 rc = -ENOMEM;
3509 goto out_fail;
3510 }
3511
Steve French8b217fe2016-11-11 22:36:20 -06003512 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003513 if (ses->server->vals->protocol_id == 0) {
3514 cifs_dbg(VFS,
3515 "Use SMB2 or later for snapshot mount option\n");
3516 rc = -EOPNOTSUPP;
3517 goto out_fail;
3518 } else
3519 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003520 }
3521
Steve Frenchca567eb2019-03-29 16:31:07 -05003522 if (volume_info->handle_timeout) {
3523 if (ses->server->vals->protocol_id == 0) {
3524 cifs_dbg(VFS,
3525 "Use SMB2.1 or later for handle timeout option\n");
3526 rc = -EOPNOTSUPP;
3527 goto out_fail;
3528 } else
3529 tcon->handle_timeout = volume_info->handle_timeout;
3530 }
3531
Jeff Laytond00c28d2010-04-24 07:57:44 -04003532 tcon->ses = ses;
3533 if (volume_info->password) {
3534 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3535 if (!tcon->password) {
3536 rc = -ENOMEM;
3537 goto out_fail;
3538 }
3539 }
3540
Steve French23657ad2018-04-22 15:14:58 -05003541 if (volume_info->seal) {
3542 if (ses->server->vals->protocol_id == 0) {
3543 cifs_dbg(VFS,
3544 "SMB3 or later required for encryption\n");
3545 rc = -EOPNOTSUPP;
3546 goto out_fail;
3547 } else if (tcon->ses->server->capabilities &
3548 SMB2_GLOBAL_CAP_ENCRYPTION)
3549 tcon->seal = true;
3550 else {
3551 cifs_dbg(VFS, "Encryption is not supported on share\n");
3552 rc = -EOPNOTSUPP;
3553 goto out_fail;
3554 }
3555 }
3556
Steve French8505c8b2018-06-18 14:01:59 -05003557 if (volume_info->linux_ext) {
3558 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003559 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003560 printk_once(KERN_WARNING
3561 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003562 } else {
3563 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3564 rc = -EOPNOTSUPP;
3565 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003566 }
Steve Frenchb3266142018-05-20 23:41:10 -05003567 }
Steve Frenchb3266142018-05-20 23:41:10 -05003568
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003569 /*
3570 * BB Do we need to wrap session_mutex around this TCon call and Unix
3571 * SetFS as we do on SessSetup and reconnect?
3572 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003573 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003574 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3575 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003576 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003577 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003578 if (rc)
3579 goto out_fail;
3580
Steve Frenchb618f002015-11-03 09:15:03 -06003581 tcon->use_persistent = false;
3582 /* check if SMB2 or later, CIFS does not support persistent handles */
3583 if (volume_info->persistent) {
3584 if (ses->server->vals->protocol_id == 0) {
3585 cifs_dbg(VFS,
3586 "SMB3 or later required for persistent handles\n");
3587 rc = -EOPNOTSUPP;
3588 goto out_fail;
3589 } else if (ses->server->capabilities &
3590 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3591 tcon->use_persistent = true;
3592 else /* persistent handles requested but not supported */ {
3593 cifs_dbg(VFS,
3594 "Persistent handles not supported on share\n");
3595 rc = -EOPNOTSUPP;
3596 goto out_fail;
3597 }
3598 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3599 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3600 && (volume_info->nopersistent == false)) {
3601 cifs_dbg(FYI, "enabling persistent handles\n");
3602 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003603 } else if (volume_info->resilient) {
3604 if (ses->server->vals->protocol_id == 0) {
3605 cifs_dbg(VFS,
3606 "SMB2.1 or later required for resilient handles\n");
3607 rc = -EOPNOTSUPP;
3608 goto out_fail;
3609 }
3610 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003611 }
3612
Steve Frenchcae53f72019-09-03 17:49:46 -05003613 /* If the user really knows what they are doing they can override */
3614 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3615 if (volume_info->cache_ro)
3616 cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3617 else if (volume_info->cache_rw)
3618 cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3619 }
3620
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003621 /*
3622 * We can have only one retry value for a connection to a share so for
3623 * resources mounted more than once to the same server share the last
3624 * value passed in for the retry flag is used.
3625 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003626 tcon->retry = volume_info->retry;
3627 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003628 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003629 tcon->local_lease = volume_info->local_lease;
Steve French3e7a02d2019-09-11 21:46:20 -05003630 tcon->no_lease = volume_info->no_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003631 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003632
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303633 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003634 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303635 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003636
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303637 cifs_fscache_get_super_cookie(tcon);
3638
Jeff Laytond00c28d2010-04-24 07:57:44 -04003639 return tcon;
3640
3641out_fail:
3642 tconInfoFree(tcon);
3643 return ERR_PTR(rc);
3644}
3645
Jeff Layton9d002df2010-10-06 19:51:11 -04003646void
3647cifs_put_tlink(struct tcon_link *tlink)
3648{
3649 if (!tlink || IS_ERR(tlink))
3650 return;
3651
3652 if (!atomic_dec_and_test(&tlink->tl_count) ||
3653 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3654 tlink->tl_time = jiffies;
3655 return;
3656 }
3657
3658 if (!IS_ERR(tlink_tcon(tlink)))
3659 cifs_put_tcon(tlink_tcon(tlink));
3660 kfree(tlink);
3661 return;
3662}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003663
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003664static int
3665compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3666{
3667 struct cifs_sb_info *old = CIFS_SB(sb);
3668 struct cifs_sb_info *new = mnt_data->cifs_sb;
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003669 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3670 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003671
3672 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3673 return 0;
3674
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003675 if (old->mnt_cifs_serverino_autodisabled)
3676 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3677
3678 if (oldflags != newflags)
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003679 return 0;
3680
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003681 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003682 * We want to share sb only if we don't specify an r/wsize or
3683 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003684 */
3685 if (new->wsize && new->wsize < old->wsize)
3686 return 0;
3687
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003688 if (new->rsize && new->rsize < old->rsize)
3689 return 0;
3690
Eric W. Biederman1f682332013-02-06 01:20:20 -08003691 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003692 return 0;
3693
3694 if (old->mnt_file_mode != new->mnt_file_mode ||
3695 old->mnt_dir_mode != new->mnt_dir_mode)
3696 return 0;
3697
3698 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3699 return 0;
3700
3701 if (old->actimeo != new->actimeo)
3702 return 0;
3703
3704 return 1;
3705}
3706
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003707static int
3708match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3709{
3710 struct cifs_sb_info *old = CIFS_SB(sb);
3711 struct cifs_sb_info *new = mnt_data->cifs_sb;
Ronnie Sahlbergfe129262020-01-22 11:07:56 +10003712 bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3713 old->prepath;
3714 bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3715 new->prepath;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003716
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003717 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003718 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003719 else if (!old_set && !new_set)
3720 return 1;
3721
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003722 return 0;
3723}
3724
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003725int
3726cifs_match_super(struct super_block *sb, void *data)
3727{
3728 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3729 struct smb_vol *volume_info;
3730 struct cifs_sb_info *cifs_sb;
3731 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003732 struct cifs_ses *ses;
3733 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003734 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003735 int rc = 0;
3736
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003737 spin_lock(&cifs_tcp_ses_lock);
3738 cifs_sb = CIFS_SB(sb);
3739 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3740 if (IS_ERR(tlink)) {
3741 spin_unlock(&cifs_tcp_ses_lock);
3742 return rc;
3743 }
3744 tcon = tlink_tcon(tlink);
3745 ses = tcon->ses;
3746 tcp_srv = ses->server;
3747
3748 volume_info = mnt_data->vol;
3749
Jeff Layton9fa114f2012-11-26 11:09:57 -05003750 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003751 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003752 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003753 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003754 rc = 0;
3755 goto out;
3756 }
3757
3758 rc = compare_mount_options(sb, mnt_data);
3759out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003760 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003761 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003762 return rc;
3763}
3764
Jeff Layton09e50d52008-07-23 10:11:19 -04003765#ifdef CONFIG_DEBUG_LOCK_ALLOC
3766static struct lock_class_key cifs_key[2];
3767static struct lock_class_key cifs_slock_key[2];
3768
3769static inline void
3770cifs_reclassify_socket4(struct socket *sock)
3771{
3772 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003773 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003774 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3775 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3776}
3777
3778static inline void
3779cifs_reclassify_socket6(struct socket *sock)
3780{
3781 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003782 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003783 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3784 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3785}
3786#else
3787static inline void
3788cifs_reclassify_socket4(struct socket *sock)
3789{
3790}
3791
3792static inline void
3793cifs_reclassify_socket6(struct socket *sock)
3794{
3795}
3796#endif
3797
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003799static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800{
Steve French50c2f752007-07-13 00:33:32 +00003801 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802
Steve French50c2f752007-07-13 00:33:32 +00003803 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 /* mask a nibble at a time and encode */
3805 target[j] = 'A' + (0x0F & (source[i] >> 4));
3806 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003807 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808 }
3809
3810}
3811
Ben Greear3eb9a882010-09-01 17:06:02 -07003812static int
3813bind_socket(struct TCP_Server_Info *server)
3814{
3815 int rc = 0;
3816 if (server->srcaddr.ss_family != AF_UNSPEC) {
3817 /* Bind to the specified local IP address */
3818 struct socket *socket = server->ssocket;
3819 rc = socket->ops->bind(socket,
3820 (struct sockaddr *) &server->srcaddr,
3821 sizeof(server->srcaddr));
3822 if (rc < 0) {
3823 struct sockaddr_in *saddr4;
3824 struct sockaddr_in6 *saddr6;
3825 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3826 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3827 if (saddr6->sin6_family == AF_INET6)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003828 cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003829 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003830 else
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003831 cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003832 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003833 }
3834 }
3835 return rc;
3836}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
3838static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003839ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840{
3841 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003842 /*
3843 * some servers require RFC1001 sessinit before sending
3844 * negprot - BB check reconnection in case where second
3845 * sessinit is sent but no second negprot
3846 */
3847 struct rfc1002_session_packet *ses_init_buf;
3848 struct smb_hdr *smb_buf;
3849 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3850 GFP_KERNEL);
3851 if (ses_init_buf) {
3852 ses_init_buf->trailer.session_req.called_len = 32;
3853
Colin Ian King997152f2016-01-25 16:25:54 +00003854 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003855 rfc1002mangle(ses_init_buf->trailer.
3856 session_req.called_name,
3857 server->server_RFC1001_name,
3858 RFC1001_NAME_LEN_WITH_NULL);
3859 else
3860 rfc1002mangle(ses_init_buf->trailer.
3861 session_req.called_name,
3862 DEFAULT_CIFS_CALLED_NAME,
3863 RFC1001_NAME_LEN_WITH_NULL);
3864
3865 ses_init_buf->trailer.session_req.calling_len = 32;
3866
3867 /*
3868 * calling name ends in null (byte 16) from old smb
3869 * convention.
3870 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003871 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003872 rfc1002mangle(ses_init_buf->trailer.
3873 session_req.calling_name,
3874 server->workstation_RFC1001_name,
3875 RFC1001_NAME_LEN_WITH_NULL);
3876 else
3877 rfc1002mangle(ses_init_buf->trailer.
3878 session_req.calling_name,
3879 "LINUX_CIFS_CLNT",
3880 RFC1001_NAME_LEN_WITH_NULL);
3881
3882 ses_init_buf->trailer.session_req.scope1 = 0;
3883 ses_init_buf->trailer.session_req.scope2 = 0;
3884 smb_buf = (struct smb_hdr *)ses_init_buf;
3885
3886 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003887 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003888 rc = smb_send(server, smb_buf, 0x44);
3889 kfree(ses_init_buf);
3890 /*
3891 * RFC1001 layer in at least one server
3892 * requires very short break before negprot
3893 * presumably because not expecting negprot
3894 * to follow so fast. This is a simple
3895 * solution that works without
3896 * complicating the code and causes no
3897 * significant slowing down on mount
3898 * for everyone else
3899 */
3900 usleep_range(1000, 2000);
3901 }
3902 /*
3903 * else the negprot may still work without this
3904 * even though malloc failed
3905 */
3906
3907 return rc;
3908}
3909
3910static int
3911generic_ip_connect(struct TCP_Server_Info *server)
3912{
3913 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003914 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003915 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003916 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003917 struct sockaddr *saddr;
3918
3919 saddr = (struct sockaddr *) &server->dstaddr;
3920
3921 if (server->dstaddr.ss_family == AF_INET6) {
3922 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3923 slen = sizeof(struct sockaddr_in6);
3924 sfamily = AF_INET6;
3925 } else {
3926 sport = ((struct sockaddr_in *) saddr)->sin_port;
3927 slen = sizeof(struct sockaddr_in);
3928 sfamily = AF_INET;
3929 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003931 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003932 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3933 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 if (rc < 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003935 cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003936 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003939
3940 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003941 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003942 server->ssocket = socket;
3943 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003944 if (sfamily == AF_INET6)
3945 cifs_reclassify_socket6(socket);
3946 else
3947 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 }
3949
Ben Greear3eb9a882010-09-01 17:06:02 -07003950 rc = bind_socket(server);
3951 if (rc < 0)
3952 return rc;
3953
Jeff Laytond5c56052008-12-01 18:42:33 -05003954 /*
3955 * Eventually check for other socket options to change from
3956 * the default. sock_setsockopt not used because it expects
3957 * user space buffer
3958 */
3959 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003960 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003961
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003962 /* make the bufsizes depend on wsize/rsize and max requests */
3963 if (server->noautotune) {
3964 if (socket->sk->sk_sndbuf < (200 * 1024))
3965 socket->sk->sk_sndbuf = 200 * 1024;
3966 if (socket->sk->sk_rcvbuf < (140 * 1024))
3967 socket->sk->sk_rcvbuf = 140 * 1024;
3968 }
3969
Steve French6a5fa2362010-01-01 01:28:43 +00003970 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003971 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003972 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3973 (char *)&val, sizeof(val));
3974 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003975 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3976 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003977 }
3978
Joe Perchesf96637b2013-05-04 22:12:25 -05003979 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003980 socket->sk->sk_sndbuf,
3981 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3982
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003983 rc = socket->ops->connect(socket, saddr, slen,
3984 server->noblockcnt ? O_NONBLOCK : 0);
Paulo Alcantara (SUSE)d532cc72019-10-10 12:31:58 -03003985 /*
3986 * When mounting SMB root file systems, we do not want to block in
3987 * connect. Otherwise bail out and then let cifs_reconnect() perform
3988 * reconnect failover - if possible.
3989 */
3990 if (server->noblockcnt && rc == -EINPROGRESS)
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003991 rc = 0;
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003992 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003993 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003994 sock_release(socket);
3995 server->ssocket = NULL;
3996 return rc;
3997 }
3998
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003999 if (sport == htons(RFC1001_PORT))
4000 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00004001
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 return rc;
4003}
4004
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03004005static int
4006ip_connect(struct TCP_Server_Info *server)
4007{
Steve French6da97912011-03-13 18:55:55 +00004008 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03004009 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
4010 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
4011
4012 if (server->dstaddr.ss_family == AF_INET6)
4013 sport = &addr6->sin6_port;
4014 else
4015 sport = &addr->sin_port;
4016
4017 if (*sport == 0) {
4018 int rc;
4019
4020 /* try with 445 port at first */
4021 *sport = htons(CIFS_PORT);
4022
4023 rc = generic_ip_connect(server);
4024 if (rc >= 0)
4025 return rc;
4026
4027 /* if it failed, try with 139 port */
4028 *sport = htons(RFC1001_PORT);
4029 }
4030
4031 return generic_ip_connect(server);
4032}
4033
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004034void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04004035 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00004036{
4037 /* if we are reconnecting then should we check to see if
4038 * any requested capabilities changed locally e.g. via
4039 * remount but we can not do much about it here
4040 * if they have (even if we could detect it by the following)
4041 * Perhaps we could add a backpointer to array of sb from tcon
4042 * or if we change to make all sb to same share the same
4043 * sb as NFS - then we only have one backpointer to sb.
4044 * What if we wanted to mount the server share twice once with
4045 * and once without posixacls or posix paths? */
4046 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00004047
Steve Frenchc18c8422007-07-18 23:21:09 +00004048 if (vol_info && vol_info->no_linux_ext) {
4049 tcon->fsUnixInfo.Capability = 0;
4050 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05004051 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004052 return;
4053 } else if (vol_info)
4054 tcon->unix_ext = 1; /* Unix Extensions supported */
4055
4056 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004057 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004058 return;
4059 }
Steve French50c2f752007-07-13 00:33:32 +00004060
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004061 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00004062 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05004063 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00004064 /* check for reconnect case in which we do not
4065 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004066 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004067 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00004068 originally at mount time */
4069 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
4070 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004071 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
4072 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004073 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00004074 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004075 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004076 cifs_dbg(VFS, "possible reconnect error\n");
4077 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00004078 }
Steve French8af18972007-02-14 04:42:51 +00004079 }
Steve French50c2f752007-07-13 00:33:32 +00004080
Steve French6848b732011-05-26 18:38:54 +00004081 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004082 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00004083
Steve French8af18972007-02-14 04:42:51 +00004084 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00004085 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00004086 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004087 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004088 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004089 if (cifs_sb)
4090 cifs_sb->mnt_cifs_flags |=
4091 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00004092 }
4093
Steve French75865f8c2007-06-24 18:30:48 +00004094 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00004095 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004096 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004097 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004098 if (cifs_sb)
4099 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00004100 CIFS_MOUNT_POSIX_PATHS;
4101 }
Steve French50c2f752007-07-13 00:33:32 +00004102
Joe Perchesf96637b2013-05-04 22:12:25 -05004103 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00004104#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00004105 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004106 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004107 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004108 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004109 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004110 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004111 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004112 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004113 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004114 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004115 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004116 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004117 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004118 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00004119 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004120 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00004121 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004122 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00004123#endif /* CIFS_DEBUG2 */
4124 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00004125 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004126 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00004127 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05004128 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 +00004129
Steve French8af18972007-02-14 04:42:51 +00004130 }
4131 }
4132}
4133
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004134int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004135 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004136{
Jeff Layton2de970f2010-10-06 19:51:12 -04004137 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
4138
Al Viro2ced6f62011-06-17 09:20:04 -04004139 spin_lock_init(&cifs_sb->tlink_tree_lock);
4140 cifs_sb->tlink_tree = RB_ROOT;
4141
Steve Frenche8506d22019-02-28 21:32:15 -06004142 cifs_sb->bsize = pvolume_info->bsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004143 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004144 * Temporarily set r/wsize for matching superblock. If we end up using
4145 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004146 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004147 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004148 cifs_sb->wsize = pvolume_info->wsize;
4149
Steve French3b795212008-11-13 19:45:32 +00004150 cifs_sb->mnt_uid = pvolume_info->linux_uid;
4151 cifs_sb->mnt_gid = pvolume_info->linux_gid;
4152 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
4153 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05004154 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
4155 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00004156
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304157 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004158 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304159
Aurelien Aptel83930722018-09-20 18:10:25 -07004160 if (pvolume_info->nodfs)
4161 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00004162 if (pvolume_info->noperm)
4163 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4164 if (pvolume_info->setuids)
4165 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05004166 if (pvolume_info->setuidfromacl)
4167 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00004168 if (pvolume_info->server_ino)
4169 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4170 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05004171 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
4172 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00004173 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4174 if (pvolume_info->no_xattr)
4175 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4176 if (pvolume_info->sfu_emul)
4177 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4178 if (pvolume_info->nobrl)
4179 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05004180 if (pvolume_info->nohandlecache)
4181 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00004182 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00004183 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00004184 if (pvolume_info->mand_lock)
4185 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00004186 if (pvolume_info->rwpidforward)
4187 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French412094a2019-06-24 02:01:42 -05004188 if (pvolume_info->mode_ace)
4189 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
Steve French3b795212008-11-13 19:45:32 +00004190 if (pvolume_info->cifs_acl)
4191 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004192 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004193 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004194 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
4195 }
4196 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004197 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004198 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
4199 }
Steve French3b795212008-11-13 19:45:32 +00004200 if (pvolume_info->override_uid)
4201 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
4202 if (pvolume_info->override_gid)
4203 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
4204 if (pvolume_info->dynperm)
4205 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05304206 if (pvolume_info->fsc)
4207 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04004208 if (pvolume_info->multiuser)
4209 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
4210 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05004211 if (pvolume_info->strict_io)
4212 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00004213 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004214 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00004215 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
4216 }
Steve French83bbfa72019-08-27 23:58:54 -05004217 if (pvolume_info->cache_ro) {
4218 cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4219 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
Steve French41e033f2019-08-30 02:12:41 -05004220 } else if (pvolume_info->cache_rw) {
4221 cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4222 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4223 CIFS_MOUNT_RW_CACHE);
Steve French83bbfa72019-08-27 23:58:54 -05004224 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004225 if (pvolume_info->mfsymlinks) {
4226 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05004227 /*
4228 * Our SFU ("Services for Unix" emulation does not allow
4229 * creating symlinks but does allow reading existing SFU
4230 * symlinks (it does allow both creating and reading SFU
4231 * style mknod and FIFOs though). When "mfsymlinks" and
4232 * "sfu" are both enabled at the same time, it allows
4233 * reading both types of symlinks, but will only create
4234 * them with mfsymlinks format. This allows better
4235 * Apple compatibility (probably better for Samba too)
4236 * while still recognizing old Windows style symlinks.
4237 */
4238 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004239 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05004240 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004241 }
Steve French3b795212008-11-13 19:45:32 +00004242
4243 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05004244 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004245
4246 if (pvolume_info->prepath) {
4247 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
4248 if (cifs_sb->prepath == NULL)
4249 return -ENOMEM;
4250 }
4251
4252 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004253}
4254
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004255void
4256cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004257{
Sean Finneyb9468452011-04-11 13:19:32 +00004258 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004259 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02004260 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00004261 kfree(volume_info->domainname);
4262 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004263 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004264}
4265
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004266void
4267cifs_cleanup_volume_info(struct smb_vol *volume_info)
4268{
4269 if (!volume_info)
4270 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004271 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004272 kfree(volume_info);
4273}
4274
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004275/* Release all succeed connections */
4276static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4277 unsigned int xid,
4278 struct TCP_Server_Info *server,
4279 struct cifs_ses *ses, struct cifs_tcon *tcon)
4280{
4281 int rc = 0;
4282
4283 if (tcon)
4284 cifs_put_tcon(tcon);
4285 else if (ses)
4286 cifs_put_smb_ses(ses);
4287 else if (server)
4288 cifs_put_tcp_session(server, 0);
4289 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4290 free_xid(xid);
4291}
4292
4293/* Get connections for tcp, ses and tcon */
4294static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4295 unsigned int *xid,
4296 struct TCP_Server_Info **nserver,
4297 struct cifs_ses **nses, struct cifs_tcon **ntcon)
4298{
4299 int rc = 0;
4300 struct TCP_Server_Info *server;
4301 struct cifs_ses *ses;
4302 struct cifs_tcon *tcon;
4303
4304 *nserver = NULL;
4305 *nses = NULL;
4306 *ntcon = NULL;
4307
4308 *xid = get_xid();
4309
4310 /* get a reference to a tcp session */
4311 server = cifs_get_tcp_session(vol);
4312 if (IS_ERR(server)) {
4313 rc = PTR_ERR(server);
4314 return rc;
4315 }
4316
4317 *nserver = server;
4318
4319 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
4320 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4321 else
4322 server->max_credits = vol->max_credits;
4323
4324 /* get a reference to a SMB session */
4325 ses = cifs_get_smb_ses(server, vol);
4326 if (IS_ERR(ses)) {
4327 rc = PTR_ERR(ses);
4328 return rc;
4329 }
4330
4331 *nses = ses;
4332
4333 if ((vol->persistent == true) && (!(ses->server->capabilities &
4334 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004335 cifs_server_dbg(VFS, "persistent handles not supported by server\n");
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004336 return -EOPNOTSUPP;
4337 }
4338
4339 /* search for existing tcon to this server share */
4340 tcon = cifs_get_tcon(ses, vol);
4341 if (IS_ERR(tcon)) {
4342 rc = PTR_ERR(tcon);
4343 return rc;
4344 }
4345
4346 *ntcon = tcon;
4347
4348 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4349 if (tcon->posix_extensions)
4350 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4351
4352 /* tell server which Unix caps we support */
4353 if (cap_unix(tcon->ses)) {
4354 /*
4355 * reset of caps checks mount to see if unix extensions disabled
4356 * for just this mount.
4357 */
4358 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4359 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4360 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4361 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4362 return -EACCES;
4363 } else
4364 tcon->unix_ext = 0; /* server does not support them */
4365
4366 /* do not care if a following call succeed - informational */
Steve French1981eba2019-08-29 22:33:38 -05004367 if (!tcon->pipe && server->ops->qfs_tcon) {
Amir Goldstein0f060932020-02-03 21:46:43 +02004368 server->ops->qfs_tcon(*xid, tcon, cifs_sb);
Steve French1981eba2019-08-29 22:33:38 -05004369 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4370 if (tcon->fsDevInfo.DeviceCharacteristics &
Steve French52870d52019-10-01 21:25:46 -05004371 cpu_to_le32(FILE_READ_ONLY_DEVICE))
Steve French1981eba2019-08-29 22:33:38 -05004372 cifs_dbg(VFS, "mounted to read only share\n");
Steve French41e033f2019-08-30 02:12:41 -05004373 else if ((cifs_sb->mnt_cifs_flags &
4374 CIFS_MOUNT_RW_CACHE) == 0)
Steve French1981eba2019-08-29 22:33:38 -05004375 cifs_dbg(VFS, "read only mount of RW share\n");
Steve French41e033f2019-08-30 02:12:41 -05004376 /* no need to log a RW mount of a typical RW share */
Steve French1981eba2019-08-29 22:33:38 -05004377 }
4378 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004379
4380 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4381 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4382
4383 return 0;
4384}
4385
4386static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4387 struct cifs_tcon *tcon)
4388{
4389 struct tcon_link *tlink;
4390
4391 /* hang the tcon off of the superblock */
4392 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4393 if (tlink == NULL)
4394 return -ENOMEM;
4395
4396 tlink->tl_uid = ses->linux_uid;
4397 tlink->tl_tcon = tcon;
4398 tlink->tl_time = jiffies;
4399 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4400 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4401
4402 cifs_sb->master_tlink = tlink;
4403 spin_lock(&cifs_sb->tlink_tree_lock);
4404 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4405 spin_unlock(&cifs_sb->tlink_tree_lock);
4406
4407 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4408 TLINK_IDLE_EXPIRE);
4409 return 0;
4410}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004411
Steve French2d6d5892009-04-09 00:36:44 +00004412#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004413/*
4414 * cifs_build_path_to_root returns full path to root when we do not have an
4415 * exiting connection (tcon)
4416 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004417static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004418build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004419 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004420{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004421 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004422 unsigned int pplen = useppath && vol->prepath ?
4423 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004424 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004425
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004426 if (unc_len > MAX_TREE_SIZE)
4427 return ERR_PTR(-EINVAL);
4428
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004429 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004430 if (full_path == NULL)
4431 return ERR_PTR(-ENOMEM);
4432
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004433 memcpy(full_path, vol->UNC, unc_len);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004434 pos = full_path + unc_len;
4435
4436 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004437 *pos = CIFS_DIR_SEP(cifs_sb);
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004438 memcpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004439 pos += pplen;
4440 }
4441
4442 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004443 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004444 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004445 return full_path;
4446}
Sean Finneydd613942011-04-11 13:19:30 +00004447
Paulo Alcantara1c780222018-11-14 16:24:03 -02004448/**
4449 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4450 *
Sean Finneydd613942011-04-11 13:19:30 +00004451 *
Sean Finney046462a2011-04-11 13:19:33 +00004452 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4453 * to a string containing updated options for the submount. Otherwise it
4454 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004455 *
4456 * Returns the rc from get_dfs_path to the caller, which can be used to
4457 * determine whether there were referrals.
4458 */
4459static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004460expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004461 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00004462 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00004463{
4464 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004465 struct dfs_info3_param referral = {0};
Sean Finneydd613942011-04-11 13:19:30 +00004466 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4467
Aurelien Aptel83930722018-09-20 18:10:25 -07004468 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4469 return -EREMOTE;
4470
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004471 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004472 if (IS_ERR(full_path))
4473 return PTR_ERR(full_path);
4474
4475 /* For DFS paths, skip the first '\' of the UNC */
4476 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4477
Paulo Alcantara1c780222018-11-14 16:24:03 -02004478 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4479 ref_path, &referral, NULL);
4480 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004481 char *fake_devname = NULL;
4482
4483 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004484 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004485 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004486 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004487
Sean Finneydd613942011-04-11 13:19:30 +00004488 if (IS_ERR(mdata)) {
4489 rc = PTR_ERR(mdata);
4490 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004491 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004492 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004493 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004494 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004495 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004496 kfree(fake_devname);
4497 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004498 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004499 }
4500 kfree(full_path);
4501 return rc;
4502}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004503
4504static inline int get_next_dfs_tgt(const char *path,
4505 struct dfs_cache_tgt_list *tgt_list,
4506 struct dfs_cache_tgt_iterator **tgt_it)
4507{
4508 if (!*tgt_it)
4509 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4510 else
4511 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4512 return !*tgt_it ? -EHOSTDOWN : 0;
4513}
4514
4515static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4516 struct smb_vol *fake_vol, struct smb_vol *vol)
4517{
4518 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4519 int len = strlen(tgt) + 2;
4520 char *new_unc;
4521
4522 new_unc = kmalloc(len, GFP_KERNEL);
4523 if (!new_unc)
4524 return -ENOMEM;
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +10004525 scnprintf(new_unc, len, "\\%s", tgt);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004526
4527 kfree(vol->UNC);
4528 vol->UNC = new_unc;
4529
4530 if (fake_vol->prepath) {
4531 kfree(vol->prepath);
4532 vol->prepath = fake_vol->prepath;
4533 fake_vol->prepath = NULL;
4534 }
4535 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4536
4537 return 0;
4538}
4539
4540static int setup_dfs_tgt_conn(const char *path,
4541 const struct dfs_cache_tgt_iterator *tgt_it,
4542 struct cifs_sb_info *cifs_sb,
4543 struct smb_vol *vol,
4544 unsigned int *xid,
4545 struct TCP_Server_Info **server,
4546 struct cifs_ses **ses,
4547 struct cifs_tcon **tcon)
4548{
4549 int rc;
4550 struct dfs_info3_param ref = {0};
4551 char *mdata = NULL, *fake_devname = NULL;
Steve Frenchd0959b02019-10-05 10:53:58 -05004552 struct smb_vol fake_vol = {NULL};
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004553
4554 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4555
4556 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4557 if (rc)
4558 return rc;
4559
4560 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4561 &fake_devname);
4562 free_dfs_info_param(&ref);
4563
4564 if (IS_ERR(mdata)) {
4565 rc = PTR_ERR(mdata);
4566 mdata = NULL;
4567 } else {
4568 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4569 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4570 false);
4571 }
4572 kfree(mdata);
4573 kfree(fake_devname);
4574
4575 if (!rc) {
4576 /*
4577 * We use a 'fake_vol' here because we need pass it down to the
4578 * mount_{get,put} functions to test connection against new DFS
4579 * targets.
4580 */
4581 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4582 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4583 tcon);
4584 if (!rc) {
4585 /*
4586 * We were able to connect to new target server.
4587 * Update current volume info with new target server.
4588 */
4589 rc = update_vol_info(tgt_it, &fake_vol, vol);
4590 }
4591 }
4592 cifs_cleanup_volume_info_contents(&fake_vol);
4593 return rc;
4594}
4595
4596static int mount_do_dfs_failover(const char *path,
4597 struct cifs_sb_info *cifs_sb,
4598 struct smb_vol *vol,
4599 struct cifs_ses *root_ses,
4600 unsigned int *xid,
4601 struct TCP_Server_Info **server,
4602 struct cifs_ses **ses,
4603 struct cifs_tcon **tcon)
4604{
4605 int rc;
4606 struct dfs_cache_tgt_list tgt_list;
4607 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4608
4609 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4610 return -EOPNOTSUPP;
4611
4612 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4613 if (rc)
4614 return rc;
4615
4616 for (;;) {
4617 /* Get next DFS target server - if any */
4618 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4619 if (rc)
4620 break;
4621 /* Connect to next DFS target */
4622 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4623 ses, tcon);
4624 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4625 break;
4626 }
4627 if (!rc) {
4628 /*
4629 * Update DFS target hint in DFS referral cache with the target
4630 * server we successfully reconnected to.
4631 */
4632 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4633 cifs_sb->local_nls,
4634 cifs_remap(cifs_sb), path,
4635 tgt_it);
4636 }
4637 dfs_cache_free_tgts(&tgt_list);
4638 return rc;
4639}
Steve French2d6d5892009-04-09 00:36:44 +00004640#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004641
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004642int
Jeff Layton04db79b2011-07-06 08:10:38 -04004643cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004644 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004646 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004647
Steve Frenchc7c137b2018-06-06 17:59:29 -05004648 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004649 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650
Jeff Layton7586b762008-12-01 18:41:49 -05004651 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004652 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004653 kfree(volume_info->username);
4654 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004655 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004657 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004659 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004660 /* In userspace mount helper we can get user name from alternate
4661 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004662 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663 }
4664
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004666 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004667 /* load_nls_default cannot return null */
4668 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004670 volume_info->local_nls = load_nls(volume_info->iocharset);
4671 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004672 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004673 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004674 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004675 }
4676 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004677
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004678 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004679}
4680
4681struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004682cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004683{
4684 int rc;
4685 struct smb_vol *volume_info;
4686
Jeff Layton6ee95422012-11-26 11:09:57 -05004687 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004688 if (!volume_info)
4689 return ERR_PTR(-ENOMEM);
4690
Steve Frenchc7c137b2018-06-06 17:59:29 -05004691 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004692 if (rc) {
4693 cifs_cleanup_volume_info(volume_info);
4694 volume_info = ERR_PTR(rc);
4695 }
4696
4697 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004698}
4699
Aurelien Aptela6b50582016-05-25 19:59:09 +02004700static int
4701cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4702 unsigned int xid,
4703 struct cifs_tcon *tcon,
4704 struct cifs_sb_info *cifs_sb,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004705 char *full_path,
4706 int added_treename)
Aurelien Aptela6b50582016-05-25 19:59:09 +02004707{
4708 int rc;
4709 char *s;
4710 char sep, tmp;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004711 int skip = added_treename ? 1 : 0;
Aurelien Aptela6b50582016-05-25 19:59:09 +02004712
4713 sep = CIFS_DIR_SEP(cifs_sb);
4714 s = full_path;
4715
4716 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4717 while (rc == 0) {
4718 /* skip separators */
4719 while (*s == sep)
4720 s++;
4721 if (!*s)
4722 break;
4723 /* next separator */
4724 while (*s && *s != sep)
4725 s++;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004726 /*
4727 * if the treename is added, we then have to skip the first
4728 * part within the separators
4729 */
4730 if (skip) {
4731 skip = 0;
4732 continue;
4733 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004734 /*
4735 * temporarily null-terminate the path at the end of
4736 * the current component
4737 */
4738 tmp = *s;
4739 *s = 0;
4740 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4741 full_path);
4742 *s = tmp;
4743 }
4744 return rc;
4745}
4746
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004747/*
4748 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4749 * otherwise 0.
4750 */
4751static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4752 const unsigned int xid,
4753 struct TCP_Server_Info *server,
4754 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004755{
Jeff Layton1daaae82012-03-21 06:30:40 -04004756 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004757 char *full_path;
4758
4759 if (!server->ops->is_path_accessible)
4760 return -EOPNOTSUPP;
4761
4762 /*
4763 * cifs_build_path_to_root works only when we have a valid tcon
4764 */
4765 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4766 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4767 if (full_path == NULL)
4768 return -ENOMEM;
4769
4770 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4771
4772 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4773 full_path);
4774 if (rc != 0 && rc != -EREMOTE) {
4775 kfree(full_path);
4776 return rc;
4777 }
4778
4779 if (rc != -EREMOTE) {
4780 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004781 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004782 if (rc != 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004783 cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004784 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4785 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4786 rc = 0;
4787 }
4788 }
4789
4790 kfree(full_path);
4791 return rc;
4792}
4793
4794#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004795static inline void set_root_tcon(struct cifs_sb_info *cifs_sb,
4796 struct cifs_tcon *tcon,
4797 struct cifs_tcon **root)
4798{
4799 spin_lock(&cifs_tcp_ses_lock);
4800 tcon->tc_count++;
4801 tcon->remap = cifs_remap(cifs_sb);
4802 spin_unlock(&cifs_tcp_ses_lock);
4803 *root = tcon;
4804}
4805
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004806int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4807{
4808 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004809 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004810 struct cifs_ses *ses;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004811 struct cifs_tcon *root_tcon = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004812 struct cifs_tcon *tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004813 struct TCP_Server_Info *server;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004814 char *root_path = NULL, *full_path = NULL;
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004815 char *old_mountdata, *origin_mountdata = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004816 int count;
Al Virodd854462011-06-17 08:24:42 -04004817
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004818 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4819 if (!rc && tcon) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004820 /* If not a standalone DFS root, then check if path is remote */
4821 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4822 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4823 NULL);
4824 if (rc) {
4825 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4826 if (!rc)
4827 goto out;
4828 if (rc != -EREMOTE)
4829 goto error;
4830 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004831 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004832 /*
4833 * If first DFS target server went offline and we failed to connect it,
4834 * server and ses pointers are NULL at this point, though we still have
4835 * chance to get a cached DFS referral in expand_dfs_referral() and
4836 * retry next target available in it.
4837 *
4838 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4839 * performed against DFS path and *no* requests will be sent to server
4840 * for any new DFS referrals. Hence it's safe to skip checking whether
4841 * server or ses ptr is NULL.
4842 */
4843 if (rc == -EACCES || rc == -EOPNOTSUPP)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004844 goto error;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004845
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004846 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4847 if (IS_ERR(root_path)) {
4848 rc = PTR_ERR(root_path);
4849 root_path = NULL;
4850 goto error;
4851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004852
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004853 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4854 if (IS_ERR(full_path)) {
4855 rc = PTR_ERR(full_path);
4856 full_path = NULL;
4857 goto error;
4858 }
Sean Finneyc1508ca2011-04-11 13:19:31 +00004859 /*
4860 * Perform an unconditional check for whether there are DFS
4861 * referrals for this path without prefix, to provide support
4862 * for DFS referrals from w2k8 servers which don't seem to respond
4863 * with PATH_NOT_COVERED to requests that include the prefix.
4864 * Chase the referral if found, otherwise continue normally.
4865 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004866 old_mountdata = cifs_sb->mountdata;
4867 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004868
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004869 if (cifs_sb->mountdata == NULL) {
4870 rc = -ENOENT;
4871 goto error;
4872 }
4873
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004874 /* Save DFS root volume information for DFS refresh worker */
4875 origin_mountdata = kstrndup(cifs_sb->mountdata,
4876 strlen(cifs_sb->mountdata), GFP_KERNEL);
4877 if (!origin_mountdata) {
4878 rc = -ENOMEM;
4879 goto error;
4880 }
4881
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004882 if (cifs_sb->mountdata != old_mountdata) {
4883 /* If we were redirected, reconnect to new target server */
4884 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4885 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4886 }
4887 if (rc) {
4888 if (rc == -EACCES || rc == -EOPNOTSUPP)
4889 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004890 /* Perform DFS failover to any other DFS targets */
4891 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4892 &xid, &server, &ses, &tcon);
4893 if (rc)
4894 goto error;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004895 }
4896
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004897 kfree(root_path);
4898 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4899 if (IS_ERR(root_path)) {
4900 rc = PTR_ERR(root_path);
4901 root_path = NULL;
4902 goto error;
4903 }
4904 /* Cache out resolved root server */
4905 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4906 root_path + 1, NULL, NULL);
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004907 kfree(root_path);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004908 root_path = NULL;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004909
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004910 set_root_tcon(cifs_sb, tcon, &root_tcon);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004911
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004912 for (count = 1; ;) {
4913 if (!rc && tcon) {
4914 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4915 if (!rc || rc != -EREMOTE)
4916 break;
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004917 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004918 /*
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004919 * BB: when we implement proper loop detection,
4920 * we will remove this check. But now we need it
4921 * to prevent an indefinite loop if 'DFS tree' is
4922 * misconfigured (i.e. has loops).
Steve French6d3ea7e2012-11-28 22:34:41 -06004923 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004924 if (count++ > MAX_NESTED_LINKS) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004925 rc = -ELOOP;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004926 break;
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004927 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004928
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004929 kfree(full_path);
4930 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4931 if (IS_ERR(full_path)) {
4932 rc = PTR_ERR(full_path);
4933 full_path = NULL;
4934 break;
4935 }
4936
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004937 old_mountdata = cifs_sb->mountdata;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004938 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004939 true);
4940 if (rc)
4941 break;
Jeff Layton7b91e262009-07-23 15:22:30 -04004942
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004943 if (cifs_sb->mountdata != old_mountdata) {
4944 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4945 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4946 &tcon);
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004947 /*
4948 * Ensure that DFS referrals go through new root server.
4949 */
4950 if (!rc && tcon &&
4951 (tcon->share_flags & (SHI1005_FLAGS_DFS |
4952 SHI1005_FLAGS_DFS_ROOT))) {
4953 cifs_put_tcon(root_tcon);
4954 set_root_tcon(cifs_sb, tcon, &root_tcon);
4955 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004956 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004957 if (rc) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004958 if (rc == -EACCES || rc == -EOPNOTSUPP)
4959 break;
4960 /* Perform DFS failover to any other DFS targets */
4961 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4962 root_tcon->ses, &xid,
4963 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004964 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4965 !ses)
4966 goto error;
4967 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004968 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004969 cifs_put_tcon(root_tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004970
Jeff Layton9d002df2010-10-06 19:51:11 -04004971 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004972 goto error;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004973
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004974 spin_lock(&cifs_tcp_ses_lock);
4975 if (!tcon->dfs_path) {
4976 /* Save full path in new tcon to do failover when reconnecting tcons */
4977 tcon->dfs_path = full_path;
4978 full_path = NULL;
4979 tcon->remap = cifs_remap(cifs_sb);
4980 }
4981 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
YueHaibing2f0a6172018-12-18 01:34:39 +00004982 strlen(tcon->dfs_path),
4983 GFP_ATOMIC);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004984 if (!cifs_sb->origin_fullpath) {
4985 spin_unlock(&cifs_tcp_ses_lock);
4986 rc = -ENOMEM;
4987 goto error;
4988 }
4989 spin_unlock(&cifs_tcp_ses_lock);
4990
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004991 rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath);
Paulo Alcantarae511d312018-11-14 17:16:44 -02004992 if (rc) {
4993 kfree(cifs_sb->origin_fullpath);
4994 goto error;
4995 }
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004996 /*
4997 * After reconnecting to a different server, unique ids won't
4998 * match anymore, so we disable serverino. This prevents
4999 * dentry revalidation to think the dentry are stale (ESTALE).
5000 */
5001 cifs_autodisable_serverino(cifs_sb);
Jeff Layton70fe7dc2007-11-16 22:21:07 +00005002out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04005003 free_xid(xid);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02005004 cifs_try_adding_channels(ses);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02005005 return mount_setup_tlink(cifs_sb, ses, tcon);
5006
5007error:
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02005008 kfree(full_path);
5009 kfree(root_path);
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03005010 kfree(origin_mountdata);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02005011 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012 return rc;
5013}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02005014#else
5015int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
5016{
5017 int rc = 0;
5018 unsigned int xid;
5019 struct cifs_ses *ses;
5020 struct cifs_tcon *tcon;
5021 struct TCP_Server_Info *server;
5022
5023 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
5024 if (rc)
5025 goto error;
5026
5027 if (tcon) {
5028 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
5029 if (rc == -EREMOTE)
5030 rc = -EOPNOTSUPP;
5031 if (rc)
5032 goto error;
5033 }
5034
5035 free_xid(xid);
5036
5037 return mount_setup_tlink(cifs_sb, ses, tcon);
5038
5039error:
5040 mount_put_conns(cifs_sb, xid, server, ses, tcon);
5041 return rc;
5042}
5043#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044
Jeff Layton8d1bca32011-06-11 21:17:10 -04005045/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01005046 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04005047 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04005049CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00005050 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051 const struct nls_table *nls_codepage)
5052{
5053 struct smb_hdr *smb_buffer;
5054 struct smb_hdr *smb_buffer_response;
5055 TCONX_REQ *pSMB;
5056 TCONX_RSP *pSMBr;
5057 unsigned char *bcc_ptr;
5058 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05005059 int length;
5060 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061
5062 if (ses == NULL)
5063 return -EIO;
5064
5065 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00005066 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00005068
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069 smb_buffer_response = smb_buffer;
5070
5071 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
5072 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07005073
Pavel Shilovsky88257362012-05-23 14:01:59 +04005074 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075 smb_buffer->Uid = ses->Suid;
5076 pSMB = (TCONX_REQ *) smb_buffer;
5077 pSMBr = (TCONX_RSP *) smb_buffer_response;
5078
5079 pSMB->AndXCommand = 0xFF;
5080 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005081 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01005082 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08005083 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00005084 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08005085 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00005086 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08005087 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005088 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08005089 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
5090 specified as required (when that support is added to
5091 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00005092 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08005093 by Samba (not sure whether other servers allow
5094 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00005095#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04005096 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05005097 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05005098 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00005099 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05005100 SECMODE_PW_ENCRYPT ? true : false,
5101 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00005102 else
5103#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06005104 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05005105 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05005106 if (rc) {
5107 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
5108 __func__, rc);
5109 cifs_buf_release(smb_buffer);
5110 return rc;
5111 }
Steve Frencheeac8042006-01-13 21:34:58 -08005112
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005113 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005114 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00005115 /* must align unicode strings */
5116 *bcc_ptr = 0; /* null byte password */
5117 bcc_ptr++;
5118 }
Steve Frencheeac8042006-01-13 21:34:58 -08005119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120
Jeff Layton38d77c52013-05-26 07:01:00 -04005121 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
5123
5124 if (ses->capabilities & CAP_STATUS32) {
5125 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
5126 }
5127 if (ses->capabilities & CAP_DFS) {
5128 smb_buffer->Flags2 |= SMBFLG2_DFS;
5129 }
5130 if (ses->capabilities & CAP_UNICODE) {
5131 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
5132 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06005133 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00005134 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00005135 (/* server len*/ + 256 /* share len */), nls_codepage);
5136 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137 bcc_ptr += 2; /* skip trailing null */
5138 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005139 strcpy(bcc_ptr, tree);
5140 bcc_ptr += strlen(tree) + 1;
5141 }
5142 strcpy(bcc_ptr, "?????");
5143 bcc_ptr += strlen("?????");
5144 bcc_ptr += 1;
5145 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00005146 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
5147 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005148 pSMB->ByteCount = cpu_to_le16(count);
5149
Steve French133672e2007-11-13 22:41:37 +00005150 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05005151 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01005154 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00005155 bool is_unicode;
5156
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00005158 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159 tcon->tid = smb_buffer_response->Tid;
5160 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05005161 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005162 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00005163 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
5164 is_unicode = true;
5165 else
5166 is_unicode = false;
5167
Jeff Laytoncc20c032009-04-30 07:16:21 -04005168
Steve French50c2f752007-07-13 00:33:32 +00005169 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00005170 if (length == 3) {
5171 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
5172 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05005173 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01005174 tcon->ipc = true;
5175 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00005176 }
5177 } else if (length == 2) {
5178 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
5179 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05005180 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00005181 }
5182 }
Steve French50c2f752007-07-13 00:33:32 +00005183 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04005184 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05005185 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04005186
5187 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04005188 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06005189 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00005190 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04005191 nls_codepage);
5192
Joe Perchesf96637b2013-05-04 22:12:25 -05005193 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005194
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005195 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00005196 (smb_buffer_response->WordCount == 7))
5197 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00005198 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
5199 else
5200 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05005201 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005202 }
5203
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00005204 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005205 return rc;
5206}
5207
Al Viro2e32cf52013-10-03 12:53:37 -04005208static void delayed_free(struct rcu_head *p)
5209{
5210 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
5211 unload_nls(sbi->local_nls);
5212 kfree(sbi);
5213}
5214
Al Viro2a9b9952011-06-17 09:27:16 -04005215void
5216cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217{
Jeff Laytonb647c352010-10-28 11:16:44 -04005218 struct rb_root *root = &cifs_sb->tlink_tree;
5219 struct rb_node *node;
5220 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005221
Jeff Layton2de970f2010-10-06 19:51:12 -04005222 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
5223
Jeff Laytonb647c352010-10-28 11:16:44 -04005224 spin_lock(&cifs_sb->tlink_tree_lock);
5225 while ((node = rb_first(root))) {
5226 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5227 cifs_get_tlink(tlink);
5228 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5229 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00005230
Jeff Laytonb647c352010-10-28 11:16:44 -04005231 spin_unlock(&cifs_sb->tlink_tree_lock);
5232 cifs_put_tlink(tlink);
5233 spin_lock(&cifs_sb->tlink_tree_lock);
5234 }
5235 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005236
Al Virod757d712011-06-17 09:42:43 -04005237 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02005238 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005239#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02005240 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005241 kfree(cifs_sb->origin_fullpath);
5242#endif
Al Viro2e32cf52013-10-03 12:53:37 -04005243 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00005244}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005246int
5247cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248{
5249 int rc = 0;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005250 struct TCP_Server_Info *server = cifs_ses_server(ses);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005252 if (!server->ops->need_neg || !server->ops->negotiate)
5253 return -ENOSYS;
5254
Jeff Layton198b5682010-04-24 07:57:48 -04005255 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005256 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04005257 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005259 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005260 if (rc == 0) {
5261 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04005262 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04005263 server->tcpStatus = CifsGood;
5264 else
5265 rc = -EHOSTDOWN;
5266 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005267 }
Steve French26b994f2008-08-06 05:11:33 +00005268
Jeff Layton198b5682010-04-24 07:57:48 -04005269 return rc;
5270}
Steve French26b994f2008-08-06 05:11:33 +00005271
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005272int
5273cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
5274 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04005275{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005276 int rc = -ENOSYS;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005277 struct TCP_Server_Info *server = cifs_ses_server(ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005278
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02005279 if (!ses->binding) {
5280 ses->capabilities = server->capabilities;
5281 if (linuxExtEnabled == 0)
5282 ses->capabilities &= (~server->vals->cap_unix);
5283
5284 if (ses->auth_key.response) {
5285 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
5286 ses->auth_key.response);
5287 kfree(ses->auth_key.response);
5288 ses->auth_key.response = NULL;
5289 ses->auth_key.len = 0;
5290 }
5291 }
Steve French20418ac2009-04-30 16:13:32 +00005292
Joe Perchesf96637b2013-05-04 22:12:25 -05005293 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00005294 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04005295
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005296 if (server->ops->sess_setup)
5297 rc = server->ops->sess_setup(xid, ses, nls_info);
5298
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05005299 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10005300 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05005301
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302 return rc;
5303}
5304
Jeff Layton8a8798a2012-01-17 16:09:15 -05005305static int
5306cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
5307{
Jeff Layton3f618222013-06-12 19:52:14 -05005308 vol->sectype = ses->sectype;
5309
5310 /* krb5 is special, since we don't need username or pw */
5311 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05005312 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05005313
5314 return cifs_set_cifscreds(vol, ses);
5315}
5316
Steve French96daf2b2011-05-27 04:34:02 +00005317static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005318cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04005319{
Jeff Layton8a8798a2012-01-17 16:09:15 -05005320 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00005321 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
5322 struct cifs_ses *ses;
5323 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04005324 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04005325
5326 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03005327 if (vol_info == NULL)
5328 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04005329
Jeff Layton9d002df2010-10-06 19:51:11 -04005330 vol_info->local_nls = cifs_sb->local_nls;
5331 vol_info->linux_uid = fsuid;
5332 vol_info->cred_uid = fsuid;
5333 vol_info->UNC = master_tcon->treeName;
5334 vol_info->retry = master_tcon->retry;
5335 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05005336 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04005337 vol_info->local_lease = master_tcon->local_lease;
5338 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04005339 vol_info->sectype = master_tcon->ses->sectype;
5340 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04005341
Jeff Layton8a8798a2012-01-17 16:09:15 -05005342 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
5343 if (rc) {
5344 tcon = ERR_PTR(rc);
5345 goto out;
5346 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005347
5348 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305349 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005350 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305351 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005352
5353 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
5354 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00005355 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07005356 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04005357 goto out;
5358 }
5359
5360 tcon = cifs_get_tcon(ses, vol_info);
5361 if (IS_ERR(tcon)) {
5362 cifs_put_smb_ses(ses);
5363 goto out;
5364 }
5365
Steve Frenchce558b02018-05-31 19:16:54 -05005366 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
5367 if (tcon->posix_extensions)
5368 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05005369
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005370 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04005371 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05005372
Jeff Layton9d002df2010-10-06 19:51:11 -04005373out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05005374 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01005375 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005376 kfree(vol_info);
5377
5378 return tcon;
5379}
5380
Steve French96daf2b2011-05-27 04:34:02 +00005381struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005382cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5383{
5384 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5385}
5386
Jeff Laytonb647c352010-10-28 11:16:44 -04005387/* find and return a tlink with given uid */
5388static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005389tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005390{
5391 struct rb_node *node = root->rb_node;
5392 struct tcon_link *tlink;
5393
5394 while (node) {
5395 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5396
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005397 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005398 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005399 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005400 node = node->rb_right;
5401 else
5402 return tlink;
5403 }
5404 return NULL;
5405}
5406
5407/* insert a tcon_link into the tree */
5408static void
5409tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5410{
5411 struct rb_node **new = &(root->rb_node), *parent = NULL;
5412 struct tcon_link *tlink;
5413
5414 while (*new) {
5415 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5416 parent = *new;
5417
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005418 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005419 new = &((*new)->rb_left);
5420 else
5421 new = &((*new)->rb_right);
5422 }
5423
5424 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5425 rb_insert_color(&new_tlink->tl_rbnode, root);
5426}
5427
Jeff Layton9d002df2010-10-06 19:51:11 -04005428/*
5429 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5430 * current task.
5431 *
5432 * If the superblock doesn't refer to a multiuser mount, then just return
5433 * the master tcon for the mount.
5434 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305435 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005436 * exists, then check to see if it's pending construction. If it is then wait
5437 * for construction to complete. Once it's no longer pending, check to see if
5438 * it failed and either return an error or retry construction, depending on
5439 * the timeout.
5440 *
5441 * If one doesn't exist then insert a new tcon_link struct into the tree and
5442 * try to construct a new one.
5443 */
5444struct tcon_link *
5445cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5446{
5447 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005448 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005449 struct tcon_link *tlink, *newtlink;
5450
5451 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5452 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5453
5454 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005455 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005456 if (tlink)
5457 cifs_get_tlink(tlink);
5458 spin_unlock(&cifs_sb->tlink_tree_lock);
5459
5460 if (tlink == NULL) {
5461 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5462 if (newtlink == NULL)
5463 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005464 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005465 newtlink->tl_tcon = ERR_PTR(-EACCES);
5466 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5467 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5468 cifs_get_tlink(newtlink);
5469
Jeff Layton9d002df2010-10-06 19:51:11 -04005470 spin_lock(&cifs_sb->tlink_tree_lock);
5471 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005472 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005473 if (tlink) {
5474 cifs_get_tlink(tlink);
5475 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005476 kfree(newtlink);
5477 goto wait_for_construction;
5478 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005479 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005480 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5481 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005482 } else {
5483wait_for_construction:
5484 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005485 TASK_INTERRUPTIBLE);
5486 if (ret) {
5487 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005488 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005489 }
5490
5491 /* if it's good, return it */
5492 if (!IS_ERR(tlink->tl_tcon))
5493 return tlink;
5494
5495 /* return error if we tried this already recently */
5496 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5497 cifs_put_tlink(tlink);
5498 return ERR_PTR(-EACCES);
5499 }
5500
5501 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5502 goto wait_for_construction;
5503 }
5504
5505 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5506 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5507 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5508
5509 if (IS_ERR(tlink->tl_tcon)) {
5510 cifs_put_tlink(tlink);
5511 return ERR_PTR(-EACCES);
5512 }
5513
5514 return tlink;
5515}
Jeff Layton2de970f2010-10-06 19:51:12 -04005516
5517/*
5518 * periodic workqueue job that scans tcon_tree for a superblock and closes
5519 * out tcons.
5520 */
5521static void
5522cifs_prune_tlinks(struct work_struct *work)
5523{
5524 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5525 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005526 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005527 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005528 struct rb_node *tmp;
5529 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005530
Jeff Laytonb647c352010-10-28 11:16:44 -04005531 /*
5532 * Because we drop the spinlock in the loop in order to put the tlink
5533 * it's not guarded against removal of links from the tree. The only
5534 * places that remove entries from the tree are this function and
5535 * umounts. Because this function is non-reentrant and is canceled
5536 * before umount can proceed, this is safe.
5537 */
5538 spin_lock(&cifs_sb->tlink_tree_lock);
5539 node = rb_first(root);
5540 while (node != NULL) {
5541 tmp = node;
5542 node = rb_next(tmp);
5543 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5544
5545 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5546 atomic_read(&tlink->tl_count) != 0 ||
5547 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5548 continue;
5549
5550 cifs_get_tlink(tlink);
5551 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5552 rb_erase(tmp, root);
5553
Jeff Layton2de970f2010-10-06 19:51:12 -04005554 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005555 cifs_put_tlink(tlink);
5556 spin_lock(&cifs_sb->tlink_tree_lock);
5557 }
5558 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005559
Jeff Laytonda472fc2012-03-23 14:40:53 -04005560 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005561 TLINK_IDLE_EXPIRE);
5562}