blob: 63830f228b4ac9b985252de3c1f08e918ace719d [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>
Eric Biggersdc920272020-03-08 22:58:20 -070024#include <linux/sched/mm.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010025#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/list.h>
27#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090028#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/pagemap.h>
30#include <linux/ctype.h>
31#include <linux/utsname.h>
32#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070033#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070034#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000035#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070036#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080037#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040038#include <linux/namei.h>
Andrew Lunnc6e970a2017-03-28 23:45:06 +020039#include <linux/uuid.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080040#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040042#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040043#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050044#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000045#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040046#include <linux/parser.h>
Christoph Hellwig2f8b5442016-11-01 07:40:13 -060047#include <linux/bvec.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include "cifspdu.h"
49#include "cifsglob.h"
50#include "cifsproto.h"
51#include "cifs_unicode.h"
52#include "cifs_debug.h"
53#include "cifs_fs_sb.h"
54#include "ntlmssp.h"
55#include "nterr.h"
56#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053057#include "fscache.h"
Pavel Shilovsky53e0e112016-11-04 11:50:31 -070058#include "smb2proto.h"
Long Li2f894642017-11-22 17:38:34 -070059#include "smbdirect.h"
Paulo Alcantara1c780222018-11-14 16:24:03 -020060#include "dns_resolve.h"
61#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
Ronnie Sahlbergfada37f2020-04-21 12:37:39 +1000378 spin_lock(&cifs_tcp_ses_lock);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200379 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
380 strlen(ipaddr));
Ronnie Sahlbergfada37f2020-04-21 12:37:39 +1000381 spin_unlock(&cifs_tcp_ses_lock);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200382 kfree(ipaddr);
383
384 return !rc ? -1 : 0;
385}
386#else
387static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
388{
389 return 0;
390}
391#endif
392
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200393#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200394/* These functions must be called with server->srv_mutex held */
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200395static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
396 struct cifs_sb_info *cifs_sb,
397 struct dfs_cache_tgt_list *tgt_list,
398 struct dfs_cache_tgt_iterator **tgt_it)
399{
400 const char *name;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200401
402 if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list ||
403 !server->nr_targets)
404 return;
405
406 if (!*tgt_it) {
407 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
408 } else {
409 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
410 if (!*tgt_it)
411 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
412 }
413
414 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
415
416 name = dfs_cache_get_tgt_name(*tgt_it);
417
418 kfree(server->hostname);
419
420 server->hostname = extract_hostname(name);
Dan Carpenter84288172019-01-05 15:25:29 +0300421 if (IS_ERR(server->hostname)) {
422 cifs_dbg(FYI,
423 "%s: failed to extract hostname from target: %ld\n",
424 __func__, PTR_ERR(server->hostname));
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200425 }
426}
427
428static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
429 struct dfs_cache_tgt_list *tl,
430 struct dfs_cache_tgt_iterator **it)
431{
432 if (!cifs_sb->origin_fullpath)
433 return -EOPNOTSUPP;
434 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
435}
436#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Jeff Laytond5c56052008-12-01 18:42:33 -0500438/*
439 * cifs tcp session reconnection
440 *
441 * mark tcp session as reconnecting so temporarily locked
442 * mark all smb sessions as reconnecting for tcp session
443 * reconnect tcp session
444 * wake up waiters on reconnection? - (not needed currently)
445 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400446int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447cifs_reconnect(struct TCP_Server_Info *server)
448{
449 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500450 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000451 struct cifs_ses *ses;
452 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000453 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400454 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200455#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300456 struct super_block *sb = NULL;
Paulo Alcantara23324402018-11-20 14:37:18 -0200457 struct cifs_sb_info *cifs_sb = NULL;
458 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200459 struct dfs_cache_tgt_iterator *tgt_it = NULL;
460#endif
Steve French50c2f752007-07-13 00:33:32 +0000461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200463 server->nr_targets = 1;
464#ifdef CONFIG_CIFS_DFS_UPCALL
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000465 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -0300466 sb = cifs_get_tcp_super(server);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300467 if (IS_ERR(sb)) {
468 rc = PTR_ERR(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200469 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
470 __func__, rc);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300471 sb = NULL;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200472 } else {
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300473 cifs_sb = CIFS_SB(sb);
474
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200475 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
Steve French55a7f002019-01-01 17:19:45 -0600476 if (rc && (rc != -EOPNOTSUPP)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000477 cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200478 __func__);
479 } else {
480 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
481 }
482 }
483 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
484 server->nr_targets);
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000485 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200486#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000487 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000488 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 next time through the loop */
490 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300491#ifdef CONFIG_CIFS_DFS_UPCALL
492 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -0300493 cifs_put_tcp_super(sb);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300494#endif
Stefan Metzmachere2e87512020-02-24 14:31:02 -0600495 wake_up(&server->response_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 return rc;
497 } else
498 server->tcpStatus = CifsNeedReconnect;
499 spin_unlock(&GlobalMid_Lock);
500 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400501 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Steve French6e4d3bb2018-09-22 11:25:04 -0500503 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500504 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
506 /* before reconnecting the tcp session, mark the smb session (uid)
507 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500508 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
509 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530510 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500511 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000512 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500513 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500514 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000515 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500516 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100518 if (ses->tcon_ipc)
519 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530521 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500522
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500524 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500525 mutex_lock(&server->srv_mutex);
Long Li1d2a4f52019-05-13 21:01:28 -0700526 if (server->ssocket) {
527 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
528 server->ssocket->state, server->ssocket->flags);
529 kernel_sock_shutdown(server->ssocket, SHUT_WR);
530 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
531 server->ssocket->state, server->ssocket->flags);
532 sock_release(server->ssocket);
533 server->ssocket = NULL;
534 }
535 server->sequence_number = 0;
536 server->session_estab = false;
537 kfree(server->session_key.response);
538 server->session_key.response = NULL;
539 server->session_key.len = 0;
540 server->lstrp = jiffies;
Long Li214bab42019-04-05 21:36:35 +0000541
542 /* mark submitted MIDs for retry and issue callback */
543 INIT_LIST_HEAD(&retry_list);
544 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
545 spin_lock(&GlobalMid_Lock);
546 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
547 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700548 kref_get(&mid_entry->refcount);
Long Li214bab42019-04-05 21:36:35 +0000549 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
550 mid_entry->mid_state = MID_RETRY_NEEDED;
551 list_move(&mid_entry->qhead, &retry_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700552 mid_entry->mid_flags |= MID_DELETED;
Long Li214bab42019-04-05 21:36:35 +0000553 }
554 spin_unlock(&GlobalMid_Lock);
Long Li1d2a4f52019-05-13 21:01:28 -0700555 mutex_unlock(&server->srv_mutex);
Long Li214bab42019-04-05 21:36:35 +0000556
557 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
558 list_for_each_safe(tmp, tmp2, &retry_list) {
559 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
560 list_del_init(&mid_entry->qhead);
561 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700562 cifs_mid_q_entry_release(mid_entry);
Long Li214bab42019-04-05 21:36:35 +0000563 }
564
Long Li1d2a4f52019-05-13 21:01:28 -0700565 if (cifs_rdma_enabled(server)) {
566 mutex_lock(&server->srv_mutex);
Long Li050b8c32019-04-04 11:35:42 -0500567 smbd_destroy(server);
Long Li1d2a4f52019-05-13 21:01:28 -0700568 mutex_unlock(&server->srv_mutex);
569 }
Jeff Layton3c1105d2011-05-22 07:09:13 -0400570
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400571 do {
Steve French6c3d8902006-07-31 22:46:20 +0000572 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300573
Jeff Layton73e216a2013-09-05 08:38:10 -0400574 mutex_lock(&server->srv_mutex);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200575 /*
576 * Set up next DFS target server (if any) for reconnect. If DFS
577 * feature is disabled, then we will retry last server we
578 * connected to before.
579 */
Long Li781a8052017-11-22 17:38:36 -0700580 if (cifs_rdma_enabled(server))
581 rc = smbd_reconnect(server);
582 else
583 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000584 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500585 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200586#ifdef CONFIG_CIFS_DFS_UPCALL
587 reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
588 &tgt_it);
589#endif
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200590 rc = reconn_set_ipaddr(server);
591 if (rc) {
592 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
593 __func__, rc);
594 }
Federico Sauter4afe2602015-03-17 17:45:28 +0100595 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700596 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 } else {
598 atomic_inc(&tcpSesReconnectCount);
Pavel Shilovsky335b7b62019-01-16 11:12:41 -0800599 set_credits(server, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000601 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000602 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000603 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100604 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400606 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500607
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200608#ifdef CONFIG_CIFS_DFS_UPCALL
609 if (tgt_it) {
610 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
611 tgt_it);
612 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000613 cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200614 __func__, rc);
615 }
616 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
617 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000618 cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200619 __func__, rc);
620 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200621 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300622
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200623 }
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300624
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -0300625 cifs_put_tcp_super(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200626#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400627 if (server->tcpStatus == CifsNeedNegotiate)
628 mod_delayed_work(cifsiod_wq, &server->echo, 0);
629
Stefan Metzmachere2e87512020-02-24 14:31:02 -0600630 wake_up(&server->response_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 return rc;
632}
633
Jeff Laytonc74093b2011-01-11 07:24:23 -0500634static void
635cifs_echo_request(struct work_struct *work)
636{
637 int rc;
638 struct TCP_Server_Info *server = container_of(work,
639 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400640 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500641
Jeff Layton247ec9b2011-02-04 17:09:50 -0500642 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400643 * If we need to renegotiate, set echo interval to zero to
644 * immediately call echo service where we can renegotiate.
645 */
646 if (server->tcpStatus == CifsNeedNegotiate)
647 echo_interval = 0;
648 else
649 echo_interval = server->echo_interval;
650
651 /*
652 * We cannot send an echo if it is disabled.
653 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500654 */
Steve French4fcd1812016-06-22 20:12:05 -0500655
656 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400657 server->tcpStatus == CifsExiting ||
658 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400659 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600660 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500661 goto requeue_echo;
662
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400663 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500664 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500665 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
666 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500667
668requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400669 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500670}
671
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400672static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400673allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400674{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400675 if (!server->bigbuf) {
676 server->bigbuf = (char *)cifs_buf_get();
677 if (!server->bigbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000678 cifs_server_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400679 msleep(3000);
680 /* retry will check if exiting */
681 return false;
682 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400683 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400684 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400685 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400686 }
687
Jeff Layton2a37ef92011-10-19 15:29:23 -0400688 if (!server->smallbuf) {
689 server->smallbuf = (char *)cifs_small_buf_get();
690 if (!server->smallbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000691 cifs_server_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400692 msleep(1000);
693 /* retry will check if exiting */
694 return false;
695 }
696 /* beginning of smb buffer is cleared in our buf_get */
697 } else {
698 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400699 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400700 }
701
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400702 return true;
703}
704
Jeff Laytonba749e62011-10-11 06:41:32 -0400705static bool
706server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400707{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300708 /*
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000709 * We need to wait 3 echo intervals to make sure we handle such
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300710 * situations right:
711 * 1s client sends a normal SMB request
Ronnie Sahlbergbecc2ba2019-07-24 11:43:49 +1000712 * 2s client gets a response
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300713 * 30s echo workqueue job pops, and decides we got a response recently
714 * and don't need to send another
715 * ...
716 * 65s kernel_recvmsg times out, and we see that we haven't gotten
717 * a response in >60s.
718 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200719 if ((server->tcpStatus == CifsGood ||
720 server->tcpStatus == CifsNeedNegotiate) &&
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000721 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000722 cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
723 (3 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400724 cifs_reconnect(server);
Jeff Laytonba749e62011-10-11 06:41:32 -0400725 return true;
726 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400727
Jeff Laytonba749e62011-10-11 06:41:32 -0400728 return false;
729}
730
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800731static inline bool
732zero_credits(struct TCP_Server_Info *server)
733{
734 int val;
735
736 spin_lock(&server->req_lock);
737 val = server->credits + server->echo_credits + server->oplock_credits;
738 if (server->in_flight == 0 && val == 0) {
739 spin_unlock(&server->req_lock);
740 return true;
741 }
742 spin_unlock(&server->req_lock);
743 return false;
744}
745
Al Viro71335662016-01-09 19:54:50 -0500746static int
747cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400748{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400749 int length = 0;
750 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400751
Al Viro71335662016-01-09 19:54:50 -0500752 smb_msg->msg_control = NULL;
753 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400754
Al Viro71335662016-01-09 19:54:50 -0500755 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500756 try_to_freeze();
757
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800758 /* reconnect if no credits and no requests in flight */
759 if (zero_credits(server)) {
760 cifs_reconnect(server);
761 return -ECONNABORTED;
762 }
763
Al Viro71335662016-01-09 19:54:50 -0500764 if (server_unresponsive(server))
765 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700766 if (cifs_rdma_enabled(server) && server->smbd_conn)
767 length = smbd_recv(server->smbd_conn, smb_msg);
768 else
769 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500770
771 if (server->tcpStatus == CifsExiting)
772 return -ESHUTDOWN;
773
774 if (server->tcpStatus == CifsNeedReconnect) {
775 cifs_reconnect(server);
776 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400777 }
778
Al Viro71335662016-01-09 19:54:50 -0500779 if (length == -ERESTARTSYS ||
780 length == -EAGAIN ||
781 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400782 /*
783 * Minimum sleep to prevent looping, allowing socket
784 * to clear and app threads to set tcpStatus
785 * CifsNeedReconnect if server hung.
786 */
787 usleep_range(1000, 2000);
788 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400789 continue;
Al Viro71335662016-01-09 19:54:50 -0500790 }
791
792 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500793 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400794 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500795 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400796 }
797 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400798 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400799}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400800
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400801int
802cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
803 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400804{
Al Viro71335662016-01-09 19:54:50 -0500805 struct msghdr smb_msg;
806 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100807 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400808
Al Viro71335662016-01-09 19:54:50 -0500809 return cifs_readv_from_socket(server, &smb_msg);
810}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400811
Al Viro71335662016-01-09 19:54:50 -0500812int
813cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700814 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500815{
816 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700817 struct bio_vec bv = {
818 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100819 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500820 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400821}
822
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400823static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400824is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400825{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400826 /*
827 * The first byte big endian of the length field,
828 * is actually not part of the length but the type
829 * with the most common, zero, as regular data.
830 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400831 switch (type) {
832 case RFC1002_SESSION_MESSAGE:
833 /* Regular SMB response */
834 return true;
835 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500836 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400837 break;
838 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500839 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400840 break;
841 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400842 /*
843 * We get this from Windows 98 instead of an error on
844 * SMB negprot response.
845 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500846 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400847 /* give server a second to clean up */
848 msleep(1000);
849 /*
850 * Always try 445 first on reconnect since we get NACK
851 * on some if we ever connected to port 139 (the NACK
852 * is since we do not begin with RFC1001 session
853 * initialize frame).
854 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400855 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400856 cifs_reconnect(server);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400857 break;
858 default:
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000859 cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400860 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400861 }
862
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400863 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400864}
865
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400866void
867dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400868{
869#ifdef CONFIG_CIFS_STATS2
870 mid->when_received = jiffies;
871#endif
872 spin_lock(&GlobalMid_Lock);
873 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400874 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400875 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400876 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000877 /*
878 * Trying to handle/dequeue a mid after the send_recv()
879 * function has finished processing it is a bug.
880 */
881 if (mid->mid_flags & MID_DELETED)
882 printk_once(KERN_WARNING
883 "trying to dequeue a deleted mid\n");
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700884 else {
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000885 list_del_init(&mid->qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700886 mid->mid_flags |= MID_DELETED;
887 }
Jeff Laytonea1f4502011-10-19 15:29:05 -0400888 spin_unlock(&GlobalMid_Lock);
889}
890
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800891static unsigned int
892smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
893{
894 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
895
896 /*
897 * SMB1 does not use credits.
898 */
899 if (server->vals->header_preamble_size)
900 return 0;
901
902 return le16_to_cpu(shdr->CreditRequest);
903}
904
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400905static void
906handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400907 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400908{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400909 if (server->ops->check_trans2 &&
910 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400911 return;
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800912 mid->credits_received = smb2_get_credits_from_hdr(buf, server);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400913 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400914 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400915 /* Was previous buf put in mpx struct for multi-rsp? */
916 if (!mid->multiRsp) {
917 /* smb buffer will be freed by user thread */
918 if (server->large_buf)
919 server->bigbuf = NULL;
920 else
921 server->smallbuf = NULL;
922 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400923 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400924}
925
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400926static void clean_demultiplex_info(struct TCP_Server_Info *server)
927{
928 int length;
929
930 /* take it off the list, if it's not already */
931 spin_lock(&cifs_tcp_ses_lock);
932 list_del_init(&server->tcp_ses_list);
933 spin_unlock(&cifs_tcp_ses_lock);
934
935 spin_lock(&GlobalMid_Lock);
936 server->tcpStatus = CifsExiting;
937 spin_unlock(&GlobalMid_Lock);
938 wake_up_all(&server->response_q);
939
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400940 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300941 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400942 if (server->credits <= 0)
943 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300944 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400945 /*
946 * Although there should not be any requests blocked on this queue it
947 * can not hurt to be paranoid and try to wake up requests that may
948 * haven been blocked when more than 50 at time were on the wire to the
949 * same server - they now will see the session is in exit state and get
950 * out of SendReceive.
951 */
952 wake_up_all(&server->request_q);
953 /* give those requests time to exit */
954 msleep(125);
Long Li050b8c32019-04-04 11:35:42 -0500955 if (cifs_rdma_enabled(server))
956 smbd_destroy(server);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400957 if (server->ssocket) {
958 sock_release(server->ssocket);
959 server->ssocket = NULL;
960 }
961
962 if (!list_empty(&server->pending_mid_q)) {
963 struct list_head dispose_list;
964 struct mid_q_entry *mid_entry;
965 struct list_head *tmp, *tmp2;
966
967 INIT_LIST_HEAD(&dispose_list);
968 spin_lock(&GlobalMid_Lock);
969 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
970 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500971 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700972 kref_get(&mid_entry->refcount);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400973 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400974 list_move(&mid_entry->qhead, &dispose_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700975 mid_entry->mid_flags |= MID_DELETED;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400976 }
977 spin_unlock(&GlobalMid_Lock);
978
979 /* now walk dispose list and issue callbacks */
980 list_for_each_safe(tmp, tmp2, &dispose_list) {
981 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500982 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400983 list_del_init(&mid_entry->qhead);
984 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700985 cifs_mid_q_entry_release(mid_entry);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400986 }
987 /* 1/8th of sec is more than enough time for them to exit */
988 msleep(125);
989 }
990
991 if (!list_empty(&server->pending_mid_q)) {
992 /*
993 * mpx threads have not exited yet give them at least the smb
994 * send timeout time for long ops.
995 *
996 * Due to delays on oplock break requests, we need to wait at
997 * least 45 seconds before giving up on a request getting a
998 * response and going ahead and killing cifsd.
999 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001000 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001001 msleep(46000);
1002 /*
1003 * If threads still have not exited they are probably never
1004 * coming home not much else we can do but free the memory.
1005 */
1006 }
1007
1008 kfree(server->hostname);
1009 kfree(server);
1010
1011 length = atomic_dec_return(&tcpSesAllocCount);
1012 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -07001013 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001014}
1015
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001016static int
Jeff Laytone9097ab2011-10-19 15:29:40 -04001017standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1018{
1019 int length;
1020 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +10001021 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001022
1023 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001024 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
1025 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001026 cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001027 cifs_reconnect(server);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +04001028 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001029 }
1030
1031 /* switch to large buffer if too big for a small one */
1032 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
1033 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001034 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001035 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001036 }
1037
1038 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001039 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001040 pdu_length - HEADER_SIZE(server) + 1
1041 + server->vals->header_preamble_size);
1042
Jeff Laytone9097ab2011-10-19 15:29:40 -04001043 if (length < 0)
1044 return length;
1045 server->total_read += length;
1046
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001047 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001048
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08001049 return cifs_handle_standard(server, mid);
1050}
1051
1052int
1053cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1054{
1055 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1056 int length;
1057
Jeff Laytone9097ab2011-10-19 15:29:40 -04001058 /*
1059 * We know that we received enough to get to the MID as we
1060 * checked the pdu_length earlier. Now check to see
1061 * if the rest of the header is OK. We borrow the length
1062 * var for the rest of the loop to avoid a new stack var.
1063 *
1064 * 48 bytes is enough to display the header and a little bit
1065 * into the payload for debugging purposes.
1066 */
Steve French373512e2015-12-18 13:05:30 -06001067 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001068 if (length != 0)
1069 cifs_dump_mem("Bad SMB: ", buf,
1070 min_t(unsigned int, server->total_read, 48));
1071
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001072 if (server->ops->is_session_expired &&
1073 server->ops->is_session_expired(buf)) {
1074 cifs_reconnect(server);
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001075 return -1;
1076 }
1077
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001078 if (server->ops->is_status_pending &&
Pavel Shilovsky66265f12019-01-23 17:11:16 -08001079 server->ops->is_status_pending(buf, server))
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001080 return -1;
1081
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001082 if (!mid)
1083 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001084
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001085 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001086 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001087}
1088
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001089static void
1090smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
1091{
1092 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
1093
1094 /*
1095 * SMB1 does not use credits.
1096 */
1097 if (server->vals->header_preamble_size)
1098 return;
1099
1100 if (shdr->CreditRequest) {
1101 spin_lock(&server->req_lock);
1102 server->credits += le16_to_cpu(shdr->CreditRequest);
1103 spin_unlock(&server->req_lock);
1104 wake_up(&server->request_q);
1105 }
1106}
1107
1108
Jeff Laytone9097ab2011-10-19 15:29:40 -04001109static int
Al Viro7c97c202011-06-21 08:51:28 -04001110cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001112 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001113 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001114 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001115 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001116 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001117 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001118 struct mid_q_entry *mids[MAX_COMPOUND];
1119 char *bufs[MAX_COMPOUND];
Eric Biggersdc920272020-03-08 22:58:20 -07001120 unsigned int noreclaim_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
Eric Biggersdc920272020-03-08 22:58:20 -07001122 noreclaim_flag = memalloc_noreclaim_save();
Joe Perchesf96637b2013-05-04 22:12:25 -05001123 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001124
1125 length = atomic_inc_return(&tcpSesAllocCount);
1126 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001127 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001129 set_freezable();
Eric W. Biederman33da8e72019-08-16 12:33:54 -05001130 allow_kernel_signal(SIGKILL);
Jeff Layton469ee612008-10-16 18:46:39 +00001131 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001132 if (try_to_freeze())
1133 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001134
Jeff Layton2a37ef92011-10-19 15:29:23 -04001135 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001136 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001137
Jeff Layton2a37ef92011-10-19 15:29:23 -04001138 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001139 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001140 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001141
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001142 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001143 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001144 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001145
1146 if (server->vals->header_preamble_size == 0)
1147 server->total_read = 0;
1148 else
1149 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001150
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001151 /*
1152 * The right amount was read from socket - 4 bytes,
1153 * so we can now interpret the length field.
1154 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001155 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001156
Joe Perchesf96637b2013-05-04 22:12:25 -05001157 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001158 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001159 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001160next_pdu:
1161 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001162
Jeff Layton89482a52011-10-19 15:28:57 -04001163 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001164 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001165 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001166 cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001167 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001168 cifs_reconnect(server);
Jeff Layton89482a52011-10-19 15:28:57 -04001169 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001170 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001171
Jeff Layton89482a52011-10-19 15:28:57 -04001172 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001173 length = cifs_read_from_socket(server,
1174 buf + server->vals->header_preamble_size,
1175 HEADER_SIZE(server) - 1
1176 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001177 if (length < 0)
1178 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001179 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001180
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001181 if (server->ops->next_header) {
1182 next_offset = server->ops->next_header(buf);
1183 if (next_offset)
1184 server->pdu_size = next_offset;
1185 }
1186
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001187 memset(mids, 0, sizeof(mids));
1188 memset(bufs, 0, sizeof(bufs));
1189 num_mids = 0;
1190
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001191 if (server->ops->is_transform_hdr &&
1192 server->ops->receive_transform &&
1193 server->ops->is_transform_hdr(buf)) {
1194 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001195 mids,
1196 bufs,
1197 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001198 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001199 mids[0] = server->ops->find_mid(server, buf);
1200 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001201 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001202
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001203 if (!mids[0] || !mids[0]->receive)
1204 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001205 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001206 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001207 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001208
Lars Persson696e4202018-06-25 14:05:25 +02001209 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001210 for (i = 0; i < num_mids; i++)
1211 if (mids[i])
1212 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001213 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001214 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001215
Steve Frenchfda35942011-01-20 18:06:34 +00001216 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001217
1218 for (i = 0; i < num_mids; i++) {
1219 if (mids[i] != NULL) {
1220 mids[i]->resp_buf_size = server->pdu_size;
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001221
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001222 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1223 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001224
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001225 cifs_mid_q_entry_release(mids[i]);
1226 } else if (server->ops->is_oplock_break &&
1227 server->ops->is_oplock_break(bufs[i],
1228 server)) {
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001229 smb2_add_credits_from_hdr(bufs[i], server);
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001230 cifs_dbg(FYI, "Received oplock break\n");
1231 } else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001232 cifs_server_dbg(VFS, "No task to wake, unknown frame "
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001233 "received! NumMids %d\n",
1234 atomic_read(&midCount));
1235 cifs_dump_mem("Received Data is: ", bufs[i],
1236 HEADER_SIZE(server));
Ronnie Sahlberg3e272572019-07-06 06:43:08 +10001237 smb2_add_credits_from_hdr(bufs[i], server);
Steve French39798772006-05-31 22:40:51 +00001238#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001239 if (server->ops->dump_detail)
1240 server->ops->dump_detail(bufs[i],
1241 server);
1242 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001243#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001244 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001245 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001246
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001247 if (pdu_length > server->pdu_size) {
1248 if (!allocate_buffers(server))
1249 continue;
1250 pdu_length -= server->pdu_size;
1251 server->total_read = 0;
1252 server->large_buf = false;
1253 buf = server->smallbuf;
1254 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001255 }
1256 } /* end while !EXITING */
1257
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001258 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001259 cifs_buf_release(server->bigbuf);
1260 if (server->smallbuf) /* no sense logging a debug message if NULL */
1261 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001263 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001264 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001265
1266 /* if server->tsk was NULL then wait for a signal before exiting */
1267 if (!task_to_wake) {
1268 set_current_state(TASK_INTERRUPTIBLE);
1269 while (!signal_pending(current)) {
1270 schedule();
1271 set_current_state(TASK_INTERRUPTIBLE);
1272 }
1273 set_current_state(TASK_RUNNING);
1274 }
1275
Eric Biggersdc920272020-03-08 22:58:20 -07001276 memalloc_noreclaim_restore(noreclaim_flag);
Jeff Layton0468a2c2008-12-01 07:09:35 -05001277 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278}
1279
Jeff Laytonc359cf32007-11-16 22:22:06 +00001280/* extract the host portion of the UNC string */
1281static char *
1282extract_hostname(const char *unc)
1283{
1284 const char *src;
1285 char *dst, *delim;
1286 unsigned int len;
1287
1288 /* skip double chars at beginning of string */
1289 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001290 if (strlen(unc) < 3)
1291 return ERR_PTR(-EINVAL);
1292 for (src = unc; *src && *src == '\\'; src++)
1293 ;
1294 if (!*src)
1295 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001296
1297 /* delimiter between hostname and sharename is always '\\' now */
1298 delim = strchr(src, '\\');
1299 if (!delim)
1300 return ERR_PTR(-EINVAL);
1301
1302 len = delim - src;
1303 dst = kmalloc((len + 1), GFP_KERNEL);
1304 if (dst == NULL)
1305 return ERR_PTR(-ENOMEM);
1306
1307 memcpy(dst, src, len);
1308 dst[len] = '\0';
1309
1310 return dst;
1311}
1312
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001313static int get_option_ul(substring_t args[], unsigned long *option)
1314{
1315 int rc;
1316 char *string;
1317
1318 string = match_strdup(args);
1319 if (string == NULL)
1320 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001321 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001322 kfree(string);
1323
1324 return rc;
1325}
1326
Eric W. Biederman3da46562013-02-06 01:37:39 -08001327static int get_option_uid(substring_t args[], kuid_t *result)
1328{
1329 unsigned long value;
1330 kuid_t uid;
1331 int rc;
1332
1333 rc = get_option_ul(args, &value);
1334 if (rc)
1335 return rc;
1336
1337 uid = make_kuid(current_user_ns(), value);
1338 if (!uid_valid(uid))
1339 return -EINVAL;
1340
1341 *result = uid;
1342 return 0;
1343}
1344
1345static int get_option_gid(substring_t args[], kgid_t *result)
1346{
1347 unsigned long value;
1348 kgid_t gid;
1349 int rc;
1350
1351 rc = get_option_ul(args, &value);
1352 if (rc)
1353 return rc;
1354
1355 gid = make_kgid(current_user_ns(), value);
1356 if (!gid_valid(gid))
1357 return -EINVAL;
1358
1359 *result = gid;
1360 return 0;
1361}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001362
1363static int cifs_parse_security_flavors(char *value,
1364 struct smb_vol *vol)
1365{
1366
1367 substring_t args[MAX_OPT_ARGS];
1368
Jeff Layton1e3cc572013-06-10 17:12:23 -05001369 /*
1370 * With mount options, the last one should win. Reset any existing
1371 * settings back to default.
1372 */
1373 vol->sectype = Unspecified;
1374 vol->sign = false;
1375
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001376 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001377 case Opt_sec_krb5p:
1378 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1379 return 1;
1380 case Opt_sec_krb5i:
1381 vol->sign = true;
1382 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001384 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001385 break;
1386 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001387 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001388 /* Fallthrough */
1389 case Opt_sec_ntlmssp:
1390 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001391 break;
1392 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001393 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001394 /* Fallthrough */
1395 case Opt_ntlm:
1396 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001397 break;
1398 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001399 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001400 /* Fallthrough */
1401 case Opt_sec_ntlmv2:
1402 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001403 break;
1404#ifdef CONFIG_CIFS_WEAK_PW_HASH
1405 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001406 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001407 break;
1408#endif
1409 case Opt_sec_none:
1410 vol->nullauth = 1;
1411 break;
1412 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001413 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001414 return 1;
1415 }
1416
1417 return 0;
1418}
1419
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001421cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1422{
1423 substring_t args[MAX_OPT_ARGS];
1424
1425 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1426 case Opt_cache_loose:
1427 vol->direct_io = false;
1428 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001429 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001430 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001431 break;
1432 case Opt_cache_strict:
1433 vol->direct_io = false;
1434 vol->strict_io = true;
Steve French83bbfa72019-08-27 23:58:54 -05001435 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001436 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001437 break;
1438 case Opt_cache_none:
1439 vol->direct_io = true;
1440 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001441 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001442 vol->cache_rw = false;
Steve French83bbfa72019-08-27 23:58:54 -05001443 break;
1444 case Opt_cache_ro:
1445 vol->direct_io = false;
1446 vol->strict_io = false;
1447 vol->cache_ro = true;
Steve French41e033f2019-08-30 02:12:41 -05001448 vol->cache_rw = false;
1449 break;
1450 case Opt_cache_rw:
1451 vol->direct_io = false;
1452 vol->strict_io = false;
1453 vol->cache_ro = false;
1454 vol->cache_rw = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001455 break;
1456 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001457 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001458 return 1;
1459 }
1460 return 0;
1461}
1462
1463static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001464cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001465{
1466 substring_t args[MAX_OPT_ARGS];
1467
1468 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001469#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001470 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001471 if (disable_legacy_dialects) {
1472 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1473 return 1;
1474 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001475 if (is_smb3) {
1476 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1477 return 1;
1478 }
Steve French8fe0c2c2020-02-28 01:32:37 -06001479 cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 "
1480 "is not recommended unless required for "
1481 "access to very old servers\n");
Jeff Layton23db65f2012-05-15 12:20:51 -04001482 vol->ops = &smb1_operations;
1483 vol->vals = &smb1_values;
1484 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001485 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001486 if (disable_legacy_dialects) {
1487 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1488 return 1;
1489 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001490 if (is_smb3) {
1491 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1492 return 1;
1493 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001494 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001495 vol->vals = &smb20_values;
1496 break;
Steve French74204512018-06-19 14:34:08 -05001497#else
1498 case Smb_1:
1499 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1500 return 1;
1501 case Smb_20:
1502 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1503 return 1;
1504#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001505 case Smb_21:
1506 vol->ops = &smb21_operations;
1507 vol->vals = &smb21_values;
1508 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001509 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001510 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001511 vol->vals = &smb30_values;
1512 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001513 case Smb_302:
1514 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1515 vol->vals = &smb302_values;
1516 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001517 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001518 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001519 vol->vals = &smb311_values;
1520 break;
Steve French9764c022017-09-17 10:41:35 -05001521 case Smb_3any:
1522 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1523 vol->vals = &smb3any_values;
1524 break;
1525 case Smb_default:
1526 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1527 vol->vals = &smbdefault_values;
1528 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001529 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001530 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001531 return 1;
1532 }
1533 return 0;
1534}
1535
Jeff Laytond387a5c2012-12-10 06:10:46 -05001536/*
1537 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1538 * fields with the result. Returns 0 on success and an error otherwise.
1539 */
1540static int
1541cifs_parse_devname(const char *devname, struct smb_vol *vol)
1542{
1543 char *pos;
1544 const char *delims = "/\\";
1545 size_t len;
1546
Yao Liu68e26722019-01-28 19:47:28 +08001547 if (unlikely(!devname || !*devname)) {
1548 cifs_dbg(VFS, "Device name not specified.\n");
1549 return -EINVAL;
1550 }
1551
Jeff Laytond387a5c2012-12-10 06:10:46 -05001552 /* make sure we have a valid UNC double delimiter prefix */
1553 len = strspn(devname, delims);
1554 if (len != 2)
1555 return -EINVAL;
1556
1557 /* find delimiter between host and sharename */
1558 pos = strpbrk(devname + 2, delims);
1559 if (!pos)
1560 return -EINVAL;
1561
1562 /* skip past delimiter */
1563 ++pos;
1564
1565 /* now go until next delimiter or end of string */
1566 len = strcspn(pos, delims);
1567
1568 /* move "pos" up to delimiter or NULL */
1569 pos += len;
1570 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1571 if (!vol->UNC)
1572 return -ENOMEM;
1573
1574 convert_delimiter(vol->UNC, '\\');
1575
Sachin Prabhu11e31642016-02-08 13:44:01 +05301576 /* skip any delimiter */
1577 if (*pos == '/' || *pos == '\\')
1578 pos++;
1579
1580 /* If pos is NULL then no prepath */
1581 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001582 return 0;
1583
1584 vol->prepath = kstrdup(pos, GFP_KERNEL);
1585 if (!vol->prepath)
1586 return -ENOMEM;
1587
1588 return 0;
1589}
1590
Jeff Layton23db65f2012-05-15 12:20:51 -04001591static int
Sean Finneyb9468452011-04-11 13:19:32 +00001592cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001593 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001595 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001596 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 unsigned int temp_len, i, j;
1598 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001599 short int override_uid = -1;
1600 short int override_gid = -1;
1601 bool uid_specified = false;
1602 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001603 bool sloppy = false;
1604 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001605 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001606 char *string = NULL;
1607 char *tmp_end, *value;
1608 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001609 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001610 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001611 unsigned short port = 0;
1612 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
1614 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001615 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001616 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
Jeff Layton6ee95422012-11-26 11:09:57 -05001618 /* ensure we always start with zeroed-out smb_vol */
1619 memset(vol, 0, sizeof(*vol));
1620
Jeff Layton88463992010-11-22 15:31:03 -05001621 /*
1622 * does not have to be perfect mapping since field is
1623 * informational, only used for servers that do not support
1624 * port 445 and it can be overridden at mount time
1625 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001626 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1627 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001628 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1629
Jeff Layton1397f2e2011-01-07 11:30:28 -05001630 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001631 /* null target name indicates to use *SMBSERVR default called name
1632 if we end up sending RFC1001 session initialize */
1633 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001634 vol->cred_uid = current_uid();
1635 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001636 vol->linux_gid = current_gid();
Steve Frenche8506d22019-02-28 21:32:15 -06001637 vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
Steve French2baa2682014-09-27 02:19:01 -05001638 /*
1639 * default to SFM style remapping of seven reserved characters
1640 * unless user overrides it or we negotiate CIFS POSIX where
1641 * it is unnecessary. Can not simultaneously use more than one mapping
1642 * since then readdir could list files that open could not open
1643 */
1644 vol->remap = true;
1645
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001646 /* default to only allowing write access to owner of the mount */
1647 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648
1649 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001650 /* default is always to request posix paths. */
1651 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001652 /* default to using server inode numbers where available */
1653 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001654
Jeff Layton1b359202012-09-19 15:20:27 -07001655 /* default is to use strict cifs caching semantics */
1656 vol->strict_io = true;
1657
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301658 vol->actimeo = CIFS_DEF_ACTIMEO;
1659
Steve Frenchca567eb2019-03-29 16:31:07 -05001660 /* Most clients set timeout to 0, allows server to use its default */
1661 vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1662
Steve French9764c022017-09-17 10:41:35 -05001663 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1664 vol->ops = &smb30_operations;
1665 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001666
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001667 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1668
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001669 /* default to no multichannel (single server connection) */
1670 vol->multichannel = false;
1671 vol->max_channels = 1;
1672
Sean Finneyb9468452011-04-11 13:19:32 +00001673 if (!mountdata)
1674 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
Sean Finneyb9468452011-04-11 13:19:32 +00001676 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1677 if (!mountdata_copy)
1678 goto cifs_parse_mount_err;
1679
1680 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001681 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001682
Steve French50c2f752007-07-13 00:33:32 +00001683 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001684 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 separator[0] = options[4];
1686 options += 5;
1687 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001688 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 }
1690 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001691 vol->backupuid_specified = false; /* no backup intent for a user */
1692 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001693
Jeff Layton37d4f992013-05-24 07:40:05 -04001694 switch (cifs_parse_devname(devname, vol)) {
1695 case 0:
1696 break;
1697 case -ENOMEM:
1698 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1699 goto cifs_parse_mount_err;
1700 case -EINVAL:
1701 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1702 goto cifs_parse_mount_err;
1703 default:
1704 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1705 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001706 }
1707
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001709 substring_t args[MAX_OPT_ARGS];
1710 unsigned long option;
1711 int token;
1712
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 if (!*data)
1714 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001716 token = match_token(data, cifs_mount_option_tokens, args);
1717
1718 switch (token) {
1719
1720 /* Ingnore the following */
1721 case Opt_ignore:
1722 break;
1723
1724 /* Boolean values */
1725 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001727 break;
1728 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001730 break;
1731 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001732 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001733 break;
1734 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001735 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001736 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001737 case Opt_forcegid:
1738 override_gid = 1;
1739 break;
1740 case Opt_noforcegid:
1741 override_gid = 0;
1742 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001743 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001744 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 break;
1746 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001747 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001748 break;
Steve French3e7a02d2019-09-11 21:46:20 -05001749 case Opt_nolease:
1750 vol->no_lease = 1;
1751 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001752 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001754 break;
1755 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001757 break;
1758 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001760 break;
1761 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001763 break;
1764 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001765 vol->sfu_remap = true;
1766 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001767 break;
1768 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001769 vol->sfu_remap = false;
1770 break;
1771 case Opt_mapposix:
1772 vol->remap = true;
1773 vol->sfu_remap = false; /* disable SFU mapping */
1774 break;
1775 case Opt_nomapposix:
1776 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001777 break;
1778 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001779 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001780 break;
1781 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001782 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001783 break;
1784 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001785 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001786 break;
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03001787 case Opt_rootfs:
1788#ifdef CONFIG_CIFS_ROOT
1789 vol->rootfs = true;
1790#endif
1791 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001792 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001793 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001794 break;
1795 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001796 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001797 break;
1798 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001799 if (vol->linux_ext)
1800 cifs_dbg(VFS,
1801 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001802 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001804 case Opt_unix:
1805 if (vol->no_linux_ext)
1806 cifs_dbg(VFS,
1807 "conflicting unix mount options\n");
1808 vol->linux_ext = 1;
1809 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001810 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001811 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001812 break;
1813 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001814 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001815 break;
1816 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001817 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001818 /*
1819 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001820 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001821 * local vfs will do advisory
1822 */
Steve French50c2f752007-07-13 00:33:32 +00001823 if (vol->file_mode ==
1824 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001825 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001826 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001827 case Opt_nohandlecache:
1828 vol->nohandlecache = 1;
1829 break;
1830 case Opt_handlecache:
1831 vol->nohandlecache = 0;
1832 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001833 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001834 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001835 break;
1836 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001838 break;
1839 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001841 break;
Steve French95932652016-09-23 01:36:34 -05001842 case Opt_setuidfromacl:
1843 vol->setuidfromacl = 1;
1844 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001845 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001846 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001847 break;
1848 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001849 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001850 break;
1851 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001853 break;
1854 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001856 break;
1857 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001859 break;
1860 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001862 break;
1863 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001864 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001865 break;
1866 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001867 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001868 break;
1869 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001871 break;
1872 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001874 break;
1875 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001876 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001877 break;
Steve French412094a2019-06-24 02:01:42 -05001878 case Opt_modesid:
1879 vol->mode_ace = 1;
1880 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001881 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001882 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001883 break;
1884 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001885 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001886 break;
1887 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001889 break;
1890 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001892 break;
1893 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001894 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001895 break;
1896 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001897 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001898 break;
Steve French4f5c10f2019-09-03 21:18:49 -05001899 case Opt_ignore_signature:
1900 vol->sign = true;
1901 vol->ignore_signature = true;
1902 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001903 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001904 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001905 * is a per tree connection (mount) not a per socket
1906 * or per-smb connection option in the protocol
1907 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1908 */
Steve French95b1cb92008-05-15 16:44:38 +00001909 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001910 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001911 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001912 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001913 break;
1914 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301915#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001916 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001917 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301918#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301919 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001920 break;
1921 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001922 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001923 break;
1924 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001925 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001926 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001927 case Opt_sloppy:
1928 sloppy = true;
1929 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001930 case Opt_nosharesock:
1931 vol->nosharesock = true;
1932 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001933 case Opt_nopersistent:
1934 vol->nopersistent = true;
1935 if (vol->persistent) {
1936 cifs_dbg(VFS,
1937 "persistenthandles mount options conflict\n");
1938 goto cifs_parse_mount_err;
1939 }
1940 break;
1941 case Opt_persistent:
1942 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001943 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001944 cifs_dbg(VFS,
1945 "persistenthandles mount options conflict\n");
1946 goto cifs_parse_mount_err;
1947 }
1948 break;
Steve French592fafe2015-11-03 10:08:53 -06001949 case Opt_resilient:
1950 vol->resilient = true;
1951 if (vol->persistent) {
1952 cifs_dbg(VFS,
1953 "persistenthandles mount options conflict\n");
1954 goto cifs_parse_mount_err;
1955 }
1956 break;
1957 case Opt_noresilient:
1958 vol->resilient = false; /* already the default */
1959 break;
Germano Percossi39566442016-12-15 12:31:18 +05301960 case Opt_domainauto:
1961 vol->domainauto = true;
1962 break;
Long Li8339dd32017-11-07 01:54:55 -07001963 case Opt_rdma:
1964 vol->rdma = true;
1965 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001966 case Opt_multichannel:
1967 vol->multichannel = true;
1968 break;
1969 case Opt_nomultichannel:
1970 vol->multichannel = false;
1971 break;
Steve French9fe5ff12019-06-24 20:39:04 -05001972 case Opt_compress:
1973 vol->compression = UNKNOWN_TYPE;
1974 cifs_dbg(VFS,
1975 "SMB3 compression support is experimental\n");
1976 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001977
1978 /* Numeric Values */
1979 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001980 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001981 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1982 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001983 goto cifs_parse_mount_err;
1984 }
1985 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001986 break;
1987 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001988 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001989 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1990 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001991 goto cifs_parse_mount_err;
1992 }
1993 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001994 break;
1995 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001996 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001997 cifs_dbg(VFS, "%s: Invalid uid value\n",
1998 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001999 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002001 uid_specified = true;
2002 break;
2003 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002004 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002005 cifs_dbg(VFS, "%s: Invalid cruid value\n",
2006 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002007 goto cifs_parse_mount_err;
2008 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002009 break;
2010 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002011 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002012 cifs_dbg(VFS, "%s: Invalid gid value\n",
2013 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002014 goto cifs_parse_mount_err;
2015 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002016 gid_specified = true;
2017 break;
2018 case Opt_file_mode:
2019 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002020 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
2021 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002022 goto cifs_parse_mount_err;
2023 }
2024 vol->file_mode = option;
2025 break;
2026 case Opt_dirmode:
2027 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002028 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
2029 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002030 goto cifs_parse_mount_err;
2031 }
2032 vol->dir_mode = option;
2033 break;
2034 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002035 if (get_option_ul(args, &option) ||
2036 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002037 cifs_dbg(VFS, "%s: Invalid port value\n",
2038 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002039 goto cifs_parse_mount_err;
2040 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002041 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002042 break;
Steve French563317e2019-09-08 23:22:02 -05002043 case Opt_min_enc_offload:
2044 if (get_option_ul(args, &option)) {
2045 cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
2046 goto cifs_parse_mount_err;
2047 }
2048 vol->min_offload = option;
2049 break;
Steve Frenche8506d22019-02-28 21:32:15 -06002050 case Opt_blocksize:
2051 if (get_option_ul(args, &option)) {
2052 cifs_dbg(VFS, "%s: Invalid blocksize value\n",
2053 __func__);
2054 goto cifs_parse_mount_err;
2055 }
2056 /*
2057 * inode blocksize realistically should never need to be
2058 * less than 16K or greater than 16M and default is 1MB.
2059 * Note that small inode block sizes (e.g. 64K) can lead
2060 * to very poor performance of common tools like cp and scp
2061 */
2062 if ((option < CIFS_MAX_MSGSIZE) ||
2063 (option > (4 * SMB3_DEFAULT_IOSIZE))) {
2064 cifs_dbg(VFS, "%s: Invalid blocksize\n",
2065 __func__);
2066 goto cifs_parse_mount_err;
2067 }
2068 vol->bsize = option;
2069 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002070 case Opt_rsize:
2071 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002072 cifs_dbg(VFS, "%s: Invalid rsize value\n",
2073 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002074 goto cifs_parse_mount_err;
2075 }
2076 vol->rsize = option;
2077 break;
2078 case Opt_wsize:
2079 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002080 cifs_dbg(VFS, "%s: Invalid wsize value\n",
2081 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002082 goto cifs_parse_mount_err;
2083 }
2084 vol->wsize = option;
2085 break;
2086 case Opt_actimeo:
2087 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002088 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
2089 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002090 goto cifs_parse_mount_err;
2091 }
2092 vol->actimeo = HZ * option;
2093 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002094 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002095 goto cifs_parse_mount_err;
2096 }
2097 break;
Steve Frenchca567eb2019-03-29 16:31:07 -05002098 case Opt_handletimeout:
2099 if (get_option_ul(args, &option)) {
2100 cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
2101 __func__);
2102 goto cifs_parse_mount_err;
2103 }
2104 vol->handle_timeout = option;
2105 if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
2106 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
2107 goto cifs_parse_mount_err;
2108 }
2109 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002110 case Opt_echo_interval:
2111 if (get_option_ul(args, &option)) {
2112 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
2113 __func__);
2114 goto cifs_parse_mount_err;
2115 }
2116 vol->echo_interval = option;
2117 break;
Steve French8b217fe2016-11-11 22:36:20 -06002118 case Opt_snapshot:
2119 if (get_option_ul(args, &option)) {
2120 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
2121 __func__);
2122 goto cifs_parse_mount_err;
2123 }
2124 vol->snapshot_time = option;
2125 break;
Steve French141891f2016-09-23 00:44:16 -05002126 case Opt_max_credits:
2127 if (get_option_ul(args, &option) || (option < 20) ||
2128 (option > 60000)) {
2129 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
2130 __func__);
2131 goto cifs_parse_mount_err;
2132 }
2133 vol->max_credits = option;
2134 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002135 case Opt_max_channels:
2136 if (get_option_ul(args, &option) || option < 1 ||
2137 option > CIFS_MAX_CHANNELS) {
2138 cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
2139 __func__, CIFS_MAX_CHANNELS);
2140 goto cifs_parse_mount_err;
2141 }
2142 vol->max_channels = option;
2143 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002144
2145 /* String Arguments */
2146
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002147 case Opt_blank_user:
2148 /* null user, ie. anonymous authentication */
2149 vol->nullauth = 1;
2150 vol->username = NULL;
2151 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002152 case Opt_user:
2153 string = match_strdup(args);
2154 if (string == NULL)
2155 goto out_nomem;
2156
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002157 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
2158 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002159 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002160 goto cifs_parse_mount_err;
2161 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002162
2163 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002164 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05002165 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002166 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002167 break;
2168 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002169 /* passwords have to be handled differently
2170 * to allow the character used for deliminator
2171 * to be passed within them
2172 */
2173
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002174 /*
2175 * Check if this is a case where the password
2176 * starts with a delimiter
2177 */
2178 tmp_end = strchr(data, '=');
2179 tmp_end++;
2180 if (!(tmp_end < end && tmp_end[1] == delim)) {
2181 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002182 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002183 vol->password = NULL;
2184 break;
2185 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +11002186 /* Fallthrough - to Opt_pass below.*/
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002187 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002188 /* Obtain the value string */
2189 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002190 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002191
2192 /* Set tmp_end to end of the string */
2193 tmp_end = (char *) value + strlen(value);
2194
2195 /* Check if following character is the deliminator
2196 * If yes, we have encountered a double deliminator
2197 * reset the NULL character to the deliminator
2198 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302199 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002200 tmp_end[0] = delim;
2201
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302202 /* Keep iterating until we get to a single
2203 * deliminator OR the end
2204 */
2205 while ((tmp_end = strchr(tmp_end, delim))
2206 != NULL && (tmp_end[1] == delim)) {
2207 tmp_end = (char *) &tmp_end[2];
2208 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002209
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302210 /* Reset var options to point to next element */
2211 if (tmp_end) {
2212 tmp_end[0] = '\0';
2213 options = (char *) &tmp_end[1];
2214 } else
2215 /* Reached the end of the mount option
2216 * string */
2217 options = end;
2218 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002219
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002220 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002221 /* Now build new password string */
2222 temp_len = strlen(value);
2223 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2224 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002225 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002226 goto cifs_parse_mount_err;
2227 }
2228
2229 for (i = 0, j = 0; i < temp_len; i++, j++) {
2230 vol->password[j] = value[i];
2231 if ((value[i] == delim) &&
2232 value[i+1] == delim)
2233 /* skip the second deliminator */
2234 i++;
2235 }
2236 vol->password[j] = '\0';
2237 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002238 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002239 /* FIXME: should this be an error instead? */
2240 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002241 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002242 case Opt_ip:
2243 string = match_strdup(args);
2244 if (string == NULL)
2245 goto out_nomem;
2246
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002247 if (!cifs_convert_address(dstaddr, string,
2248 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002249 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002250 goto cifs_parse_mount_err;
2251 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002252 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002253 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002254 case Opt_domain:
2255 string = match_strdup(args);
2256 if (string == NULL)
2257 goto out_nomem;
2258
Chen Gang057d6332013-07-19 09:01:36 +08002259 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2260 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002261 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002262 goto cifs_parse_mount_err;
2263 }
2264
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002265 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002266 vol->domainname = kstrdup(string, GFP_KERNEL);
2267 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002268 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002269 goto cifs_parse_mount_err;
2270 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002271 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002272 break;
2273 case Opt_srcaddr:
2274 string = match_strdup(args);
2275 if (string == NULL)
2276 goto out_nomem;
2277
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002278 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002279 (struct sockaddr *)&vol->srcaddr,
2280 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002281 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2282 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002283 goto cifs_parse_mount_err;
2284 }
2285 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002286 case Opt_iocharset:
2287 string = match_strdup(args);
2288 if (string == NULL)
2289 goto out_nomem;
2290
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002291 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002292 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002293 goto cifs_parse_mount_err;
2294 }
2295
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002296 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002297 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002298 vol->iocharset = kstrdup(string,
2299 GFP_KERNEL);
2300 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002301 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002302 goto cifs_parse_mount_err;
2303 }
2304 }
2305 /* if iocharset not set then load_nls_default
2306 * is used by caller
2307 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002308 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002309 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002310 case Opt_netbiosname:
2311 string = match_strdup(args);
2312 if (string == NULL)
2313 goto out_nomem;
2314
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002315 memset(vol->source_rfc1001_name, 0x20,
2316 RFC1001_NAME_LEN);
2317 /*
2318 * FIXME: are there cases in which a comma can
2319 * be valid in workstation netbios name (and
2320 * need special handling)?
2321 */
2322 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2323 /* don't ucase netbiosname for user */
2324 if (string[i] == 0)
2325 break;
2326 vol->source_rfc1001_name[i] = string[i];
2327 }
2328 /* The string has 16th byte zero still from
2329 * set at top of the function
2330 */
2331 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002332 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002333 break;
2334 case Opt_servern:
2335 /* servernetbiosname specified override *SMBSERVER */
2336 string = match_strdup(args);
2337 if (string == NULL)
2338 goto out_nomem;
2339
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002340 /* last byte, type, is 0x20 for servr type */
2341 memset(vol->target_rfc1001_name, 0x20,
2342 RFC1001_NAME_LEN_WITH_NULL);
2343
2344 /* BB are there cases in which a comma can be
2345 valid in this workstation netbios name
2346 (and need special handling)? */
2347
2348 /* user or mount helper must uppercase the
2349 netbios name */
2350 for (i = 0; i < 15; i++) {
2351 if (string[i] == 0)
2352 break;
2353 vol->target_rfc1001_name[i] = string[i];
2354 }
2355 /* The string has 16th byte zero still from
2356 set at top of the function */
2357 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002358 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002359 break;
2360 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002361 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002362 string = match_strdup(args);
2363 if (string == NULL)
2364 goto out_nomem;
2365
Steve French7e682f72017-08-31 21:34:24 -05002366 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002367 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002368 if (strlen(string) > 1) {
2369 pr_warn("Bad mount helper ver=%s. Did "
2370 "you want SMB1 (CIFS) dialect "
2371 "and mean to type vers=1.0 "
2372 "instead?\n", string);
2373 goto cifs_parse_mount_err;
2374 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002375 /* This is the default */
2376 break;
2377 }
2378 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05002379 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002380 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002381 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002382 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002383 string = match_strdup(args);
2384 if (string == NULL)
2385 goto out_nomem;
2386
Steve Frenchc7c137b2018-06-06 17:59:29 -05002387 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002388 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002389 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002390 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002391 case Opt_sec:
2392 string = match_strdup(args);
2393 if (string == NULL)
2394 goto out_nomem;
2395
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002396 if (cifs_parse_security_flavors(string, vol) != 0)
2397 goto cifs_parse_mount_err;
2398 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002399 case Opt_cache:
2400 string = match_strdup(args);
2401 if (string == NULL)
2402 goto out_nomem;
2403
2404 if (cifs_parse_cache_flavor(string, vol) != 0)
2405 goto cifs_parse_mount_err;
2406 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002407 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002408 /*
2409 * An option we don't recognize. Save it off for later
2410 * if we haven't already found one
2411 */
2412 if (!invalid)
2413 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002414 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002416 /* Free up any allocated string */
2417 kfree(string);
2418 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002420
Jeff Laytond8162552012-03-23 14:40:56 -04002421 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002422 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002423 goto cifs_parse_mount_err;
2424 }
2425
Long Li8339dd32017-11-07 01:54:55 -07002426 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2427 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2428 goto cifs_parse_mount_err;
2429 }
2430
Jeff Layton8a8798a2012-01-17 16:09:15 -05002431#ifndef CONFIG_KEYS
2432 /* Muliuser mounts require CONFIG_KEYS support */
2433 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002434 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002435 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002436 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002437#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002438 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002439 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002440 goto cifs_parse_mount_err;
2441 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002442
Jeff Layton62a1a432012-12-10 06:10:45 -05002443 /* make sure UNC has a share name */
2444 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002445 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002446 goto cifs_parse_mount_err;
2447 }
2448
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002449 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002450 int len;
2451 const char *slash;
2452
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002453 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002454 /* Use the address part of the UNC. */
2455 slash = strchr(&vol->UNC[2], '\\');
2456 len = slash - &vol->UNC[2];
2457 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002458 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002459 goto cifs_parse_mount_err;
2460 }
2461 }
2462
2463 /* set the port that we got earlier */
2464 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002466 if (uid_specified)
2467 vol->override_uid = override_uid;
2468 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002469 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002470
2471 if (gid_specified)
2472 vol->override_gid = override_gid;
2473 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002474 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002475
Steve French7e682f72017-08-31 21:34:24 -05002476 if (got_version == false)
Steve Frenchba553442020-03-04 23:56:52 -06002477 pr_warn_once("No dialect specified on mount. Default has changed"
2478 " to a more secure dialect, SMB2.1 or later (e.g. "
2479 "SMB3.1.1), from CIFS (SMB1). To use the less secure "
2480 "SMB1 dialect to access old servers which do not "
2481 "support SMB3.1.1 (or even SMB3 or SMB2.1) specify "
2482 "vers=1.0 on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002483
Sean Finneyb9468452011-04-11 13:19:32 +00002484 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002486
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002487out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002488 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002489cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002490 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002491 kfree(mountdata_copy);
2492 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493}
2494
Ben Greear3eb9a882010-09-01 17:06:02 -07002495/** Returns true if srcaddr isn't specified and rhs isn't
2496 * specified, or if srcaddr is specified and
2497 * matches the IP address of the rhs argument.
2498 */
Jeff Layton45151482010-07-06 20:43:02 -04002499static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002500srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2501{
2502 switch (srcaddr->sa_family) {
2503 case AF_UNSPEC:
2504 return (rhs->sa_family == AF_UNSPEC);
2505 case AF_INET: {
2506 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2507 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2508 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2509 }
2510 case AF_INET6: {
2511 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002512 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002513 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2514 }
2515 default:
2516 WARN_ON(1);
2517 return false; /* don't expect to be here */
2518 }
2519}
2520
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002521/*
2522 * If no port is specified in addr structure, we try to match with 445 port
2523 * and if it fails - with 139 ports. It should be called only if address
2524 * families of server and addr are equal.
2525 */
2526static bool
2527match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2528{
Steve French6da97912011-03-13 18:55:55 +00002529 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002530
Long Li3b249112019-05-15 14:09:04 -07002531 /* SMBDirect manages its own ports, don't match it here */
2532 if (server->rdma)
2533 return true;
2534
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002535 switch (addr->sa_family) {
2536 case AF_INET:
2537 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2538 port = ((struct sockaddr_in *) addr)->sin_port;
2539 break;
2540 case AF_INET6:
2541 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2542 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2543 break;
2544 default:
2545 WARN_ON(1);
2546 return false;
2547 }
2548
2549 if (!port) {
2550 port = htons(CIFS_PORT);
2551 if (port == *sport)
2552 return true;
2553
2554 port = htons(RFC1001_PORT);
2555 }
2556
2557 return port == *sport;
2558}
Ben Greear3eb9a882010-09-01 17:06:02 -07002559
2560static bool
2561match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2562 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563{
Jeff Layton45151482010-07-06 20:43:02 -04002564 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002565 case AF_INET: {
2566 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2567 struct sockaddr_in *srv_addr4 =
2568 (struct sockaddr_in *)&server->dstaddr;
2569
2570 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002571 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002572 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002573 }
2574 case AF_INET6: {
2575 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2576 struct sockaddr_in6 *srv_addr6 =
2577 (struct sockaddr_in6 *)&server->dstaddr;
2578
Jeff Layton45151482010-07-06 20:43:02 -04002579 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002580 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002581 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002582 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002583 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002584 break;
2585 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002586 default:
2587 WARN_ON(1);
2588 return false; /* don't expect to be here */
2589 }
Jeff Layton45151482010-07-06 20:43:02 -04002590
Ben Greear3eb9a882010-09-01 17:06:02 -07002591 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2592 return false;
2593
Jeff Layton45151482010-07-06 20:43:02 -04002594 return true;
2595}
2596
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002597static bool
2598match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2599{
Jeff Layton3f618222013-06-12 19:52:14 -05002600 /*
2601 * The select_sectype function should either return the vol->sectype
2602 * that was specified, or "Unspecified" if that sectype was not
2603 * compatible with the given NEGOTIATE request.
2604 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302605 if (server->ops->select_sectype(server, vol->sectype)
2606 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002607 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002608
Jeff Layton3f618222013-06-12 19:52:14 -05002609 /*
2610 * Now check if signing mode is acceptable. No need to check
2611 * global_secflags at this point since if MUST_SIGN is set then
2612 * the server->sign had better be too.
2613 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002614 if (vol->sign && !server->sign)
2615 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002616
2617 return true;
2618}
2619
Jeff Layton9fa114f2012-11-26 11:09:57 -05002620static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002621{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002622 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2623
Jeff Laytona0b3df52013-05-24 07:40:59 -04002624 if (vol->nosharesock)
2625 return 0;
2626
Steve French43cdae82019-06-13 14:26:49 -05002627 /* If multidialect negotiation see if existing sessions match one */
2628 if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2629 if (server->vals->protocol_id < SMB30_PROT_ID)
2630 return 0;
2631 } else if (strcmp(vol->vals->version_string,
2632 SMBDEFAULT_VERSION_STRING) == 0) {
2633 if (server->vals->protocol_id < SMB21_PROT_ID)
2634 return 0;
2635 } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
Jeff Layton23db65f2012-05-15 12:20:51 -04002636 return 0;
2637
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002638 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2639 return 0;
2640
2641 if (!match_address(server, addr,
2642 (struct sockaddr *)&vol->srcaddr))
2643 return 0;
2644
2645 if (!match_port(server, addr))
2646 return 0;
2647
2648 if (!match_security(server, vol))
2649 return 0;
2650
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002651 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002652 return 0;
2653
Long Li8339dd32017-11-07 01:54:55 -07002654 if (server->rdma != vol->rdma)
2655 return 0;
2656
Steve French4f5c10f2019-09-03 21:18:49 -05002657 if (server->ignore_signature != vol->ignore_signature)
2658 return 0;
2659
Steve French563317e2019-09-08 23:22:02 -05002660 if (server->min_offload != vol->min_offload)
2661 return 0;
2662
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002663 return 1;
2664}
2665
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002666struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002667cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002668{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002669 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302671 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002672 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Paulo Alcantara (SUSE)3345bb42019-12-04 11:25:06 -03002673 /*
2674 * Skip ses channels since they're only handled in lower layers
2675 * (e.g. cifs_send_recv).
2676 */
2677 if (server->is_channel || !match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002678 continue;
2679
Jeff Laytone7ddee92008-11-14 13:44:38 -05002680 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302681 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002682 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002683 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302685 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 return NULL;
2687}
2688
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002689void
2690cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002692 struct task_struct *task;
2693
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302694 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002695 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302696 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002697 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002699
Rob Landleyf1d0c992011-01-22 15:44:05 -06002700 put_net(cifs_net_ns(server));
2701
Jeff Laytone7ddee92008-11-14 13:44:38 -05002702 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302703 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002704
Jeff Laytonc74093b2011-01-11 07:24:23 -05002705 cancel_delayed_work_sync(&server->echo);
2706
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002707 if (from_reconnect)
2708 /*
2709 * Avoid deadlock here: reconnect work calls
2710 * cifs_put_tcp_session() at its end. Need to be sure
2711 * that reconnect work does nothing with server pointer after
2712 * that step.
2713 */
2714 cancel_delayed_work(&server->reconnect);
2715 else
2716 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002717
Jeff Laytone7ddee92008-11-14 13:44:38 -05002718 spin_lock(&GlobalMid_Lock);
2719 server->tcpStatus = CifsExiting;
2720 spin_unlock(&GlobalMid_Lock);
2721
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002722 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302723 cifs_fscache_release_client_cookie(server);
2724
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002725 kfree(server->session_key.response);
2726 server->session_key.response = NULL;
2727 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002728
2729 task = xchg(&server->tsk, NULL);
2730 if (task)
Eric W. Biederman72abe3b2019-05-15 12:33:50 -05002731 send_sig(SIGKILL, task, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732}
2733
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02002734struct TCP_Server_Info *
Jeff Layton63c038c2008-12-01 18:41:46 -05002735cifs_get_tcp_session(struct smb_vol *volume_info)
2736{
2737 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002738 int rc;
2739
Joe Perchesf96637b2013-05-04 22:12:25 -05002740 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002741
2742 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002743 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002744 if (tcp_ses)
2745 return tcp_ses;
2746
2747 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2748 if (!tcp_ses) {
2749 rc = -ENOMEM;
2750 goto out_err;
2751 }
2752
Jeff Layton23db65f2012-05-15 12:20:51 -04002753 tcp_ses->ops = volume_info->ops;
2754 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002755 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002756 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2757 if (IS_ERR(tcp_ses->hostname)) {
2758 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002759 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002760 }
2761
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03002762 tcp_ses->noblockcnt = volume_info->rootfs;
2763 tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
Jeff Layton63c038c2008-12-01 18:41:46 -05002764 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002765 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002766 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002767 tcp_ses->in_flight = 0;
Steve French1b63f182019-09-09 22:57:11 -05002768 tcp_ses->max_in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002769 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002770 init_waitqueue_head(&tcp_ses->response_q);
2771 init_waitqueue_head(&tcp_ses->request_q);
2772 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2773 mutex_init(&tcp_ses->srv_mutex);
2774 memcpy(tcp_ses->workstation_RFC1001_name,
2775 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2776 memcpy(tcp_ses->server_RFC1001_name,
2777 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002778 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002779 tcp_ses->sequence_number = 0;
Pavel Shilovsky5b964852019-01-18 11:30:26 -08002780 tcp_ses->reconnect_instance = 1;
Steve Frenchfda35942011-01-20 18:06:34 +00002781 tcp_ses->lstrp = jiffies;
Steve French9fe5ff12019-06-24 20:39:04 -05002782 tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
Jeff Layton58fa0152012-05-01 17:41:16 -04002783 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002784 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2785 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002786 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002787 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2788 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002789 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2790 sizeof(tcp_ses->srcaddr));
2791 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2792 sizeof(tcp_ses->dstaddr));
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002793 if (volume_info->use_client_guid)
2794 memcpy(tcp_ses->client_guid, volume_info->client_guid,
2795 SMB2_CLIENT_GUID_SIZE);
2796 else
2797 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002798 /*
2799 * at this point we are the only ones with the pointer
2800 * to the struct since the kernel thread not created yet
2801 * no need to spinlock this init of tcpStatus or srv_count
2802 */
2803 tcp_ses->tcpStatus = CifsNew;
2804 ++tcp_ses->srv_count;
2805
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002806 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2807 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2808 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2809 else
2810 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002811 if (tcp_ses->rdma) {
2812#ifndef CONFIG_CIFS_SMB_DIRECT
2813 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2814 rc = -ENOENT;
2815 goto out_err_crypto_release;
2816#endif
2817 tcp_ses->smbd_conn = smbd_get_connection(
2818 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2819 if (tcp_ses->smbd_conn) {
2820 cifs_dbg(VFS, "RDMA transport established\n");
2821 rc = 0;
2822 goto smbd_connected;
2823 } else {
2824 rc = -ENOENT;
2825 goto out_err_crypto_release;
2826 }
2827 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002828 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002829 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002830 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002831 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002832 }
Long Li2f894642017-11-22 17:38:34 -07002833smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002834 /*
2835 * since we're in a cifs function already, we know that
2836 * this will succeed. No need for try_module_get().
2837 */
2838 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002839 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002840 tcp_ses, "cifsd");
2841 if (IS_ERR(tcp_ses->tsk)) {
2842 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002843 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002844 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002845 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002846 }
Steve French563317e2019-09-08 23:22:02 -05002847 tcp_ses->min_offload = volume_info->min_offload;
Steve Frenchfd88ce92011-04-12 01:01:14 +00002848 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002849
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002850 tcp_ses->nr_targets = 1;
Steve French4f5c10f2019-09-03 21:18:49 -05002851 tcp_ses->ignore_signature = volume_info->ignore_signature;
Jeff Layton63c038c2008-12-01 18:41:46 -05002852 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302853 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002854 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302855 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002856
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302857 cifs_fscache_get_client_cookie(tcp_ses);
2858
Jeff Laytonc74093b2011-01-11 07:24:23 -05002859 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002860 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002861
Jeff Layton63c038c2008-12-01 18:41:46 -05002862 return tcp_ses;
2863
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002864out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002865 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002866
Rob Landleyf1d0c992011-01-22 15:44:05 -06002867 put_net(cifs_net_ns(tcp_ses));
2868
Jeff Layton63c038c2008-12-01 18:41:46 -05002869out_err:
2870 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002871 if (!IS_ERR(tcp_ses->hostname))
2872 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002873 if (tcp_ses->ssocket)
2874 sock_release(tcp_ses->ssocket);
2875 kfree(tcp_ses);
2876 }
2877 return ERR_PTR(rc);
2878}
2879
Steve French96daf2b2011-05-27 04:34:02 +00002880static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002881{
Jeff Layton3f618222013-06-12 19:52:14 -05002882 if (vol->sectype != Unspecified &&
2883 vol->sectype != ses->sectype)
2884 return 0;
2885
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002886 /*
2887 * If an existing session is limited to less channels than
2888 * requested, it should not be reused
2889 */
2890 if (ses->chan_max < vol->max_channels)
2891 return 0;
2892
Jeff Layton3f618222013-06-12 19:52:14 -05002893 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002894 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002895 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002896 return 0;
2897 break;
2898 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002899 /* NULL username means anonymous session */
2900 if (ses->user_name == NULL) {
2901 if (!vol->nullauth)
2902 return 0;
2903 break;
2904 }
2905
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002906 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002907 if (strncmp(ses->user_name,
2908 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002909 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002910 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002911 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002912 ses->password != NULL &&
2913 strncmp(ses->password,
2914 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002915 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002916 return 0;
2917 }
2918 return 1;
2919}
2920
Aurelien Aptelb327a712018-01-24 13:46:10 +01002921/**
2922 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2923 *
2924 * A new IPC connection is made and stored in the session
2925 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2926 */
2927static int
2928cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2929{
2930 int rc = 0, xid;
2931 struct cifs_tcon *tcon;
2932 struct nls_table *nls_codepage;
2933 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2934 bool seal = false;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002935 struct TCP_Server_Info *server = ses->server;
Aurelien Aptelb327a712018-01-24 13:46:10 +01002936
2937 /*
2938 * If the mount request that resulted in the creation of the
2939 * session requires encryption, force IPC to be encrypted too.
2940 */
2941 if (volume_info->seal) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002942 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
Aurelien Aptelb327a712018-01-24 13:46:10 +01002943 seal = true;
2944 else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002945 cifs_server_dbg(VFS,
Aurelien Aptelb327a712018-01-24 13:46:10 +01002946 "IPC: server doesn't support encryption\n");
2947 return -EOPNOTSUPP;
2948 }
2949 }
2950
2951 tcon = tconInfoAlloc();
2952 if (tcon == NULL)
2953 return -ENOMEM;
2954
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002955 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002956
2957 /* cannot fail */
2958 nls_codepage = load_nls_default();
2959
2960 xid = get_xid();
2961 tcon->ses = ses;
2962 tcon->ipc = true;
2963 tcon->seal = seal;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002964 rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002965 free_xid(xid);
2966
2967 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002968 cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002969 tconInfoFree(tcon);
2970 goto out;
2971 }
2972
2973 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2974
2975 ses->tcon_ipc = tcon;
2976out:
2977 unload_nls(nls_codepage);
2978 return rc;
2979}
2980
2981/**
2982 * cifs_free_ipc - helper to release the session IPC tcon
2983 *
2984 * Needs to be called everytime a session is destroyed
2985 */
2986static int
2987cifs_free_ipc(struct cifs_ses *ses)
2988{
2989 int rc = 0, xid;
2990 struct cifs_tcon *tcon = ses->tcon_ipc;
2991
2992 if (tcon == NULL)
2993 return 0;
2994
2995 if (ses->server->ops->tree_disconnect) {
2996 xid = get_xid();
2997 rc = ses->server->ops->tree_disconnect(xid, tcon);
2998 free_xid(xid);
2999 }
3000
3001 if (rc)
3002 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
3003
3004 tconInfoFree(tcon);
3005 ses->tcon_ipc = NULL;
3006 return rc;
3007}
3008
Steve French96daf2b2011-05-27 04:34:02 +00003009static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04003010cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011{
Steve French96daf2b2011-05-27 04:34:02 +00003012 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303014 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04003015 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003016 if (ses->status == CifsExiting)
3017 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003018 if (!match_session(ses, vol))
3019 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05003020 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303021 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003022 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303024 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 return NULL;
3026}
3027
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003028void cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05003029{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003030 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05003031 struct TCP_Server_Info *server = ses->server;
3032
Joe Perchesf96637b2013-05-04 22:12:25 -05003033 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003034
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303035 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003036 if (ses->status == CifsExiting) {
3037 spin_unlock(&cifs_tcp_ses_lock);
3038 return;
3039 }
Jeff Layton14fbf502008-11-14 13:53:46 -05003040 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303041 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003042 return;
3043 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003044 if (ses->status == CifsGood)
3045 ses->status = CifsExiting;
3046 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003047
Aurelien Aptelb327a712018-01-24 13:46:10 +01003048 cifs_free_ipc(ses);
3049
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003050 if (ses->status == CifsExiting && server->ops->logoff) {
3051 xid = get_xid();
3052 rc = server->ops->logoff(xid, ses);
3053 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003054 cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003055 __func__, rc);
3056 _free_xid(xid);
3057 }
3058
3059 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003060 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303061 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003062
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003063 /* close any extra channels */
3064 if (ses->chan_count > 1) {
3065 int i;
3066
3067 for (i = 1; i < ses->chan_count; i++)
3068 cifs_put_tcp_session(ses->chans[i].server, 0);
3069 }
3070
Jeff Layton14fbf502008-11-14 13:53:46 -05003071 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003072 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05003073}
3074
Jeff Layton8a8798a2012-01-17 16:09:15 -05003075#ifdef CONFIG_KEYS
3076
Chen Gang057d6332013-07-19 09:01:36 +08003077/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
3078#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05003079
3080/* Populate username and pw fields from keyring if possible */
3081static int
3082cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
3083{
3084 int rc = 0;
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003085 int is_domain = 0;
David Howells146aa8b2015-10-21 14:04:48 +01003086 const char *delim, *payload;
3087 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003088 ssize_t len;
3089 struct key *key;
3090 struct TCP_Server_Info *server = ses->server;
3091 struct sockaddr_in *sa;
3092 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01003093 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003094
3095 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
3096 if (!desc)
3097 return -ENOMEM;
3098
3099 /* try to find an address key first */
3100 switch (server->dstaddr.ss_family) {
3101 case AF_INET:
3102 sa = (struct sockaddr_in *)&server->dstaddr;
3103 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
3104 break;
3105 case AF_INET6:
3106 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
3107 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
3108 break;
3109 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05003110 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
3111 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003112 rc = -EINVAL;
3113 goto out_err;
3114 }
3115
Joe Perchesf96637b2013-05-04 22:12:25 -05003116 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003117 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003118 if (IS_ERR(key)) {
3119 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003120 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003121 rc = PTR_ERR(key);
3122 goto out_err;
3123 }
3124
3125 /* didn't work, try to find a domain key */
3126 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05003127 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003128 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003129 if (IS_ERR(key)) {
3130 rc = PTR_ERR(key);
3131 goto out_err;
3132 }
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003133 is_domain = 1;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003134 }
3135
3136 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00003137 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003138 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05003139 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003140 goto out_key_put;
3141 }
3142
3143 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01003144 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003145 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05003146 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003147 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003148 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
3149 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003150 rc = -EINVAL;
3151 goto out_key_put;
3152 }
3153
3154 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003155 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003156 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
3157 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003158 rc = -EINVAL;
3159 goto out_key_put;
3160 }
3161
3162 vol->username = kstrndup(payload, len, GFP_KERNEL);
3163 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003164 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
3165 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003166 rc = -ENOMEM;
3167 goto out_key_put;
3168 }
Joe Perchesf96637b2013-05-04 22:12:25 -05003169 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003170
3171 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003172 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003173 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003174 rc = -EINVAL;
3175 kfree(vol->username);
3176 vol->username = NULL;
3177 goto out_key_put;
3178 }
3179
3180 ++delim;
3181 vol->password = kstrndup(delim, len, GFP_KERNEL);
3182 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003183 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
3184 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003185 rc = -ENOMEM;
3186 kfree(vol->username);
3187 vol->username = NULL;
3188 goto out_key_put;
3189 }
3190
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003191 /*
3192 * If we have a domain key then we must set the domainName in the
3193 * for the request.
3194 */
3195 if (is_domain && ses->domainName) {
3196 vol->domainname = kstrndup(ses->domainName,
3197 strlen(ses->domainName),
3198 GFP_KERNEL);
3199 if (!vol->domainname) {
3200 cifs_dbg(FYI, "Unable to allocate %zd bytes for "
3201 "domain\n", len);
3202 rc = -ENOMEM;
3203 kfree(vol->username);
3204 vol->username = NULL;
Dan Carpenter478228e2019-08-27 13:59:17 +03003205 kzfree(vol->password);
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003206 vol->password = NULL;
3207 goto out_key_put;
3208 }
3209 }
3210
Jeff Layton8a8798a2012-01-17 16:09:15 -05003211out_key_put:
3212 up_read(&key->sem);
3213 key_put(key);
3214out_err:
3215 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05003216 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003217 return rc;
3218}
3219#else /* ! CONFIG_KEYS */
3220static inline int
3221cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
3222 struct cifs_ses *ses __attribute__((unused)))
3223{
3224 return -ENOSYS;
3225}
3226#endif /* CONFIG_KEYS */
3227
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003228/**
3229 * cifs_get_smb_ses - get a session matching @volume_info data from @server
3230 *
3231 * This function assumes it is being called from cifs_mount() where we
3232 * already got a server reference (server refcount +1). See
3233 * cifs_get_tcon() for refcount explanations.
3234 */
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003235struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04003236cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3237{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003238 int rc = -ENOMEM;
3239 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003240 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003241 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3242 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04003243
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003244 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04003245
Jeff Layton4ff67b72010-07-06 20:43:02 -04003246 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04003247 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003248 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3249 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04003250
Jeff Layton36988c72010-04-24 07:57:43 -04003251 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003252 rc = cifs_negotiate_protocol(xid, ses);
3253 if (rc) {
3254 mutex_unlock(&ses->session_mutex);
3255 /* problem -- put our ses reference */
3256 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003257 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003258 return ERR_PTR(rc);
3259 }
Jeff Layton36988c72010-04-24 07:57:43 -04003260 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003261 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003262 rc = cifs_setup_session(xid, ses,
3263 volume_info->local_nls);
3264 if (rc) {
3265 mutex_unlock(&ses->session_mutex);
3266 /* problem -- put our reference */
3267 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003268 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003269 return ERR_PTR(rc);
3270 }
3271 }
3272 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003273
3274 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003275 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003276 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003277 return ses;
3278 }
3279
Joe Perchesf96637b2013-05-04 22:12:25 -05003280 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003281 ses = sesInfoAlloc();
3282 if (ses == NULL)
3283 goto get_ses_fail;
3284
3285 /* new SMB session uses our server ref */
3286 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003287 if (server->dstaddr.ss_family == AF_INET6)
3288 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003289 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003290 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003291
Steve French8727c8a2011-02-25 01:11:56 -06003292 if (volume_info->username) {
3293 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3294 if (!ses->user_name)
3295 goto get_ses_fail;
3296 }
Jeff Layton36988c72010-04-24 07:57:43 -04003297
3298 /* volume_info->password freed at unmount */
3299 if (volume_info->password) {
3300 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3301 if (!ses->password)
3302 goto get_ses_fail;
3303 }
3304 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003305 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3306 if (!ses->domainName)
3307 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003308 }
Germano Percossi39566442016-12-15 12:31:18 +05303309 if (volume_info->domainauto)
3310 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003311 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003312 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003313
Jeff Layton28e11bd2013-05-26 07:01:00 -04003314 ses->sectype = volume_info->sectype;
3315 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003316 mutex_lock(&ses->session_mutex);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003317
3318 /* add server as first channel */
3319 ses->chans[0].server = server;
3320 ses->chan_count = 1;
3321 ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1;
3322
Jeff Layton198b5682010-04-24 07:57:48 -04003323 rc = cifs_negotiate_protocol(xid, ses);
3324 if (!rc)
3325 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003326
3327 /* each channel uses a different signing key */
3328 memcpy(ses->chans[0].signkey, ses->smb3signingkey,
3329 sizeof(ses->smb3signingkey));
3330
Jeff Layton36988c72010-04-24 07:57:43 -04003331 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003332 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003333 goto get_ses_fail;
3334
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003335 /* success, put it on the list and add it as first channel */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303336 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003337 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303338 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003339
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003340 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003341
3342 cifs_setup_ipc(ses, volume_info);
3343
Jeff Layton36988c72010-04-24 07:57:43 -04003344 return ses;
3345
3346get_ses_fail:
3347 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003348 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003349 return ERR_PTR(rc);
3350}
3351
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003352static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003353{
3354 if (tcon->tidStatus == CifsExiting)
3355 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003356 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003357 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003358 if (tcon->seal != volume_info->seal)
3359 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003360 if (tcon->snapshot_time != volume_info->snapshot_time)
3361 return 0;
Steve Frenchca567eb2019-03-29 16:31:07 -05003362 if (tcon->handle_timeout != volume_info->handle_timeout)
3363 return 0;
Steve French3e7a02d2019-09-11 21:46:20 -05003364 if (tcon->no_lease != volume_info->no_lease)
3365 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003366 return 1;
3367}
3368
Steve French96daf2b2011-05-27 04:34:02 +00003369static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003370cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371{
3372 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003373 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303375 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003376 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003377 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003378 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003379 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003380 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303381 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382 return tcon;
3383 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303384 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 return NULL;
3386}
3387
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003388void
Steve French96daf2b2011-05-27 04:34:02 +00003389cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003390{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003391 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003392 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003393
Aurelien Aptelb327a712018-01-24 13:46:10 +01003394 /*
3395 * IPC tcon share the lifetime of their session and are
3396 * destroyed in the session put function
3397 */
3398 if (tcon == NULL || tcon->ipc)
3399 return;
3400
3401 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003402 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303403 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003404 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303405 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003406 return;
3407 }
3408
3409 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303410 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003411
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003412 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003413 if (ses->server->ops->tree_disconnect)
3414 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003415 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003416
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303417 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003418 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003419 cifs_put_smb_ses(ses);
3420}
3421
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003422/**
3423 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3424 *
3425 * - tcon refcount is the number of mount points using the tcon.
3426 * - ses refcount is the number of tcon using the session.
3427 *
3428 * 1. This function assumes it is being called from cifs_mount() where
3429 * we already got a session reference (ses refcount +1).
3430 *
3431 * 2. Since we're in the context of adding a mount point, the end
3432 * result should be either:
3433 *
3434 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3435 * its session refcount incremented (1 new tcon). This +1 was
3436 * already done in (1).
3437 *
3438 * b) an existing tcon with refcount+1 (add a mount point to it) and
3439 * identical ses refcount (no new tcon). Because of (1) we need to
3440 * decrement the ses refcount.
3441 */
Steve French96daf2b2011-05-27 04:34:02 +00003442static struct cifs_tcon *
3443cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003444{
3445 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003446 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003447
Steve French8b217fe2016-11-11 22:36:20 -06003448 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003449 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003450 /*
3451 * tcon has refcount already incremented but we need to
3452 * decrement extra ses reference gotten by caller (case b)
3453 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003454 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003455 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003456 return tcon;
3457 }
3458
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003459 if (!ses->server->ops->tree_connect) {
3460 rc = -ENOSYS;
3461 goto out_fail;
3462 }
3463
Jeff Laytond00c28d2010-04-24 07:57:44 -04003464 tcon = tconInfoAlloc();
3465 if (tcon == NULL) {
3466 rc = -ENOMEM;
3467 goto out_fail;
3468 }
3469
Steve French8b217fe2016-11-11 22:36:20 -06003470 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003471 if (ses->server->vals->protocol_id == 0) {
3472 cifs_dbg(VFS,
3473 "Use SMB2 or later for snapshot mount option\n");
3474 rc = -EOPNOTSUPP;
3475 goto out_fail;
3476 } else
3477 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003478 }
3479
Steve Frenchca567eb2019-03-29 16:31:07 -05003480 if (volume_info->handle_timeout) {
3481 if (ses->server->vals->protocol_id == 0) {
3482 cifs_dbg(VFS,
3483 "Use SMB2.1 or later for handle timeout option\n");
3484 rc = -EOPNOTSUPP;
3485 goto out_fail;
3486 } else
3487 tcon->handle_timeout = volume_info->handle_timeout;
3488 }
3489
Jeff Laytond00c28d2010-04-24 07:57:44 -04003490 tcon->ses = ses;
3491 if (volume_info->password) {
3492 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3493 if (!tcon->password) {
3494 rc = -ENOMEM;
3495 goto out_fail;
3496 }
3497 }
3498
Steve French23657ad2018-04-22 15:14:58 -05003499 if (volume_info->seal) {
3500 if (ses->server->vals->protocol_id == 0) {
3501 cifs_dbg(VFS,
3502 "SMB3 or later required for encryption\n");
3503 rc = -EOPNOTSUPP;
3504 goto out_fail;
3505 } else if (tcon->ses->server->capabilities &
3506 SMB2_GLOBAL_CAP_ENCRYPTION)
3507 tcon->seal = true;
3508 else {
3509 cifs_dbg(VFS, "Encryption is not supported on share\n");
3510 rc = -EOPNOTSUPP;
3511 goto out_fail;
3512 }
3513 }
3514
Steve French8505c8b2018-06-18 14:01:59 -05003515 if (volume_info->linux_ext) {
3516 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003517 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003518 printk_once(KERN_WARNING
3519 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003520 } else {
3521 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3522 rc = -EOPNOTSUPP;
3523 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003524 }
Steve Frenchb3266142018-05-20 23:41:10 -05003525 }
Steve Frenchb3266142018-05-20 23:41:10 -05003526
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003527 /*
3528 * BB Do we need to wrap session_mutex around this TCon call and Unix
3529 * SetFS as we do on SessSetup and reconnect?
3530 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003531 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003532 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3533 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003534 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003535 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003536 if (rc)
3537 goto out_fail;
3538
Steve Frenchb618f002015-11-03 09:15:03 -06003539 tcon->use_persistent = false;
3540 /* check if SMB2 or later, CIFS does not support persistent handles */
3541 if (volume_info->persistent) {
3542 if (ses->server->vals->protocol_id == 0) {
3543 cifs_dbg(VFS,
3544 "SMB3 or later required for persistent handles\n");
3545 rc = -EOPNOTSUPP;
3546 goto out_fail;
3547 } else if (ses->server->capabilities &
3548 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3549 tcon->use_persistent = true;
3550 else /* persistent handles requested but not supported */ {
3551 cifs_dbg(VFS,
3552 "Persistent handles not supported on share\n");
3553 rc = -EOPNOTSUPP;
3554 goto out_fail;
3555 }
3556 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3557 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3558 && (volume_info->nopersistent == false)) {
3559 cifs_dbg(FYI, "enabling persistent handles\n");
3560 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003561 } else if (volume_info->resilient) {
3562 if (ses->server->vals->protocol_id == 0) {
3563 cifs_dbg(VFS,
3564 "SMB2.1 or later required for resilient handles\n");
3565 rc = -EOPNOTSUPP;
3566 goto out_fail;
3567 }
3568 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003569 }
3570
Steve Frenchcae53f72019-09-03 17:49:46 -05003571 /* If the user really knows what they are doing they can override */
3572 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3573 if (volume_info->cache_ro)
3574 cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3575 else if (volume_info->cache_rw)
3576 cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3577 }
3578
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003579 /*
3580 * We can have only one retry value for a connection to a share so for
3581 * resources mounted more than once to the same server share the last
3582 * value passed in for the retry flag is used.
3583 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003584 tcon->retry = volume_info->retry;
3585 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003586 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003587 tcon->local_lease = volume_info->local_lease;
Steve French3e7a02d2019-09-11 21:46:20 -05003588 tcon->no_lease = volume_info->no_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003589 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003590
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303591 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003592 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303593 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003594
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303595 cifs_fscache_get_super_cookie(tcon);
3596
Jeff Laytond00c28d2010-04-24 07:57:44 -04003597 return tcon;
3598
3599out_fail:
3600 tconInfoFree(tcon);
3601 return ERR_PTR(rc);
3602}
3603
Jeff Layton9d002df2010-10-06 19:51:11 -04003604void
3605cifs_put_tlink(struct tcon_link *tlink)
3606{
3607 if (!tlink || IS_ERR(tlink))
3608 return;
3609
3610 if (!atomic_dec_and_test(&tlink->tl_count) ||
3611 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3612 tlink->tl_time = jiffies;
3613 return;
3614 }
3615
3616 if (!IS_ERR(tlink_tcon(tlink)))
3617 cifs_put_tcon(tlink_tcon(tlink));
3618 kfree(tlink);
3619 return;
3620}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003621
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003622static int
3623compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3624{
3625 struct cifs_sb_info *old = CIFS_SB(sb);
3626 struct cifs_sb_info *new = mnt_data->cifs_sb;
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003627 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3628 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003629
3630 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3631 return 0;
3632
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003633 if (old->mnt_cifs_serverino_autodisabled)
3634 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3635
3636 if (oldflags != newflags)
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003637 return 0;
3638
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003639 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003640 * We want to share sb only if we don't specify an r/wsize or
3641 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003642 */
3643 if (new->wsize && new->wsize < old->wsize)
3644 return 0;
3645
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003646 if (new->rsize && new->rsize < old->rsize)
3647 return 0;
3648
Eric W. Biederman1f682332013-02-06 01:20:20 -08003649 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003650 return 0;
3651
3652 if (old->mnt_file_mode != new->mnt_file_mode ||
3653 old->mnt_dir_mode != new->mnt_dir_mode)
3654 return 0;
3655
3656 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3657 return 0;
3658
3659 if (old->actimeo != new->actimeo)
3660 return 0;
3661
3662 return 1;
3663}
3664
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003665static int
3666match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3667{
3668 struct cifs_sb_info *old = CIFS_SB(sb);
3669 struct cifs_sb_info *new = mnt_data->cifs_sb;
Ronnie Sahlbergfe129262020-01-22 11:07:56 +10003670 bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3671 old->prepath;
3672 bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3673 new->prepath;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003674
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003675 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003676 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003677 else if (!old_set && !new_set)
3678 return 1;
3679
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003680 return 0;
3681}
3682
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003683int
3684cifs_match_super(struct super_block *sb, void *data)
3685{
3686 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3687 struct smb_vol *volume_info;
3688 struct cifs_sb_info *cifs_sb;
3689 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003690 struct cifs_ses *ses;
3691 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003692 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003693 int rc = 0;
3694
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003695 spin_lock(&cifs_tcp_ses_lock);
3696 cifs_sb = CIFS_SB(sb);
3697 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3698 if (IS_ERR(tlink)) {
3699 spin_unlock(&cifs_tcp_ses_lock);
3700 return rc;
3701 }
3702 tcon = tlink_tcon(tlink);
3703 ses = tcon->ses;
3704 tcp_srv = ses->server;
3705
3706 volume_info = mnt_data->vol;
3707
Jeff Layton9fa114f2012-11-26 11:09:57 -05003708 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003709 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003710 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003711 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003712 rc = 0;
3713 goto out;
3714 }
3715
3716 rc = compare_mount_options(sb, mnt_data);
3717out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003718 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003719 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003720 return rc;
3721}
3722
Jeff Layton09e50d52008-07-23 10:11:19 -04003723#ifdef CONFIG_DEBUG_LOCK_ALLOC
3724static struct lock_class_key cifs_key[2];
3725static struct lock_class_key cifs_slock_key[2];
3726
3727static inline void
3728cifs_reclassify_socket4(struct socket *sock)
3729{
3730 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003731 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003732 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3733 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3734}
3735
3736static inline void
3737cifs_reclassify_socket6(struct socket *sock)
3738{
3739 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003740 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003741 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3742 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3743}
3744#else
3745static inline void
3746cifs_reclassify_socket4(struct socket *sock)
3747{
3748}
3749
3750static inline void
3751cifs_reclassify_socket6(struct socket *sock)
3752{
3753}
3754#endif
3755
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003757static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758{
Steve French50c2f752007-07-13 00:33:32 +00003759 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760
Steve French50c2f752007-07-13 00:33:32 +00003761 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762 /* mask a nibble at a time and encode */
3763 target[j] = 'A' + (0x0F & (source[i] >> 4));
3764 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003765 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766 }
3767
3768}
3769
Ben Greear3eb9a882010-09-01 17:06:02 -07003770static int
3771bind_socket(struct TCP_Server_Info *server)
3772{
3773 int rc = 0;
3774 if (server->srcaddr.ss_family != AF_UNSPEC) {
3775 /* Bind to the specified local IP address */
3776 struct socket *socket = server->ssocket;
3777 rc = socket->ops->bind(socket,
3778 (struct sockaddr *) &server->srcaddr,
3779 sizeof(server->srcaddr));
3780 if (rc < 0) {
3781 struct sockaddr_in *saddr4;
3782 struct sockaddr_in6 *saddr6;
3783 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3784 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3785 if (saddr6->sin6_family == AF_INET6)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003786 cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003787 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003788 else
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003789 cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003790 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003791 }
3792 }
3793 return rc;
3794}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795
3796static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003797ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798{
3799 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003800 /*
3801 * some servers require RFC1001 sessinit before sending
3802 * negprot - BB check reconnection in case where second
3803 * sessinit is sent but no second negprot
3804 */
3805 struct rfc1002_session_packet *ses_init_buf;
3806 struct smb_hdr *smb_buf;
3807 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3808 GFP_KERNEL);
3809 if (ses_init_buf) {
3810 ses_init_buf->trailer.session_req.called_len = 32;
3811
Colin Ian King997152f2016-01-25 16:25:54 +00003812 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003813 rfc1002mangle(ses_init_buf->trailer.
3814 session_req.called_name,
3815 server->server_RFC1001_name,
3816 RFC1001_NAME_LEN_WITH_NULL);
3817 else
3818 rfc1002mangle(ses_init_buf->trailer.
3819 session_req.called_name,
3820 DEFAULT_CIFS_CALLED_NAME,
3821 RFC1001_NAME_LEN_WITH_NULL);
3822
3823 ses_init_buf->trailer.session_req.calling_len = 32;
3824
3825 /*
3826 * calling name ends in null (byte 16) from old smb
3827 * convention.
3828 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003829 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003830 rfc1002mangle(ses_init_buf->trailer.
3831 session_req.calling_name,
3832 server->workstation_RFC1001_name,
3833 RFC1001_NAME_LEN_WITH_NULL);
3834 else
3835 rfc1002mangle(ses_init_buf->trailer.
3836 session_req.calling_name,
3837 "LINUX_CIFS_CLNT",
3838 RFC1001_NAME_LEN_WITH_NULL);
3839
3840 ses_init_buf->trailer.session_req.scope1 = 0;
3841 ses_init_buf->trailer.session_req.scope2 = 0;
3842 smb_buf = (struct smb_hdr *)ses_init_buf;
3843
3844 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003845 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003846 rc = smb_send(server, smb_buf, 0x44);
3847 kfree(ses_init_buf);
3848 /*
3849 * RFC1001 layer in at least one server
3850 * requires very short break before negprot
3851 * presumably because not expecting negprot
3852 * to follow so fast. This is a simple
3853 * solution that works without
3854 * complicating the code and causes no
3855 * significant slowing down on mount
3856 * for everyone else
3857 */
3858 usleep_range(1000, 2000);
3859 }
3860 /*
3861 * else the negprot may still work without this
3862 * even though malloc failed
3863 */
3864
3865 return rc;
3866}
3867
3868static int
3869generic_ip_connect(struct TCP_Server_Info *server)
3870{
3871 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003872 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003873 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003874 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003875 struct sockaddr *saddr;
3876
3877 saddr = (struct sockaddr *) &server->dstaddr;
3878
3879 if (server->dstaddr.ss_family == AF_INET6) {
3880 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3881 slen = sizeof(struct sockaddr_in6);
3882 sfamily = AF_INET6;
3883 } else {
3884 sport = ((struct sockaddr_in *) saddr)->sin_port;
3885 slen = sizeof(struct sockaddr_in);
3886 sfamily = AF_INET;
3887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003889 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003890 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3891 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 if (rc < 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003893 cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003894 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003897
3898 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003899 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003900 server->ssocket = socket;
3901 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003902 if (sfamily == AF_INET6)
3903 cifs_reclassify_socket6(socket);
3904 else
3905 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906 }
3907
Ben Greear3eb9a882010-09-01 17:06:02 -07003908 rc = bind_socket(server);
3909 if (rc < 0)
3910 return rc;
3911
Jeff Laytond5c56052008-12-01 18:42:33 -05003912 /*
3913 * Eventually check for other socket options to change from
3914 * the default. sock_setsockopt not used because it expects
3915 * user space buffer
3916 */
3917 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003918 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003919
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003920 /* make the bufsizes depend on wsize/rsize and max requests */
3921 if (server->noautotune) {
3922 if (socket->sk->sk_sndbuf < (200 * 1024))
3923 socket->sk->sk_sndbuf = 200 * 1024;
3924 if (socket->sk->sk_rcvbuf < (140 * 1024))
3925 socket->sk->sk_rcvbuf = 140 * 1024;
3926 }
3927
Steve French6a5fa2362010-01-01 01:28:43 +00003928 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003929 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003930 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3931 (char *)&val, sizeof(val));
3932 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003933 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3934 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003935 }
3936
Joe Perchesf96637b2013-05-04 22:12:25 -05003937 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003938 socket->sk->sk_sndbuf,
3939 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3940
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003941 rc = socket->ops->connect(socket, saddr, slen,
3942 server->noblockcnt ? O_NONBLOCK : 0);
Paulo Alcantara (SUSE)d532cc72019-10-10 12:31:58 -03003943 /*
3944 * When mounting SMB root file systems, we do not want to block in
3945 * connect. Otherwise bail out and then let cifs_reconnect() perform
3946 * reconnect failover - if possible.
3947 */
3948 if (server->noblockcnt && rc == -EINPROGRESS)
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003949 rc = 0;
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003950 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003951 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003952 sock_release(socket);
3953 server->ssocket = NULL;
3954 return rc;
3955 }
3956
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003957 if (sport == htons(RFC1001_PORT))
3958 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003959
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 return rc;
3961}
3962
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003963static int
3964ip_connect(struct TCP_Server_Info *server)
3965{
Steve French6da97912011-03-13 18:55:55 +00003966 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003967 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3968 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3969
3970 if (server->dstaddr.ss_family == AF_INET6)
3971 sport = &addr6->sin6_port;
3972 else
3973 sport = &addr->sin_port;
3974
3975 if (*sport == 0) {
3976 int rc;
3977
3978 /* try with 445 port at first */
3979 *sport = htons(CIFS_PORT);
3980
3981 rc = generic_ip_connect(server);
3982 if (rc >= 0)
3983 return rc;
3984
3985 /* if it failed, try with 139 port */
3986 *sport = htons(RFC1001_PORT);
3987 }
3988
3989 return generic_ip_connect(server);
3990}
3991
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003992void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003993 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003994{
3995 /* if we are reconnecting then should we check to see if
3996 * any requested capabilities changed locally e.g. via
3997 * remount but we can not do much about it here
3998 * if they have (even if we could detect it by the following)
3999 * Perhaps we could add a backpointer to array of sb from tcon
4000 * or if we change to make all sb to same share the same
4001 * sb as NFS - then we only have one backpointer to sb.
4002 * What if we wanted to mount the server share twice once with
4003 * and once without posixacls or posix paths? */
4004 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00004005
Steve Frenchc18c8422007-07-18 23:21:09 +00004006 if (vol_info && vol_info->no_linux_ext) {
4007 tcon->fsUnixInfo.Capability = 0;
4008 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05004009 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004010 return;
4011 } else if (vol_info)
4012 tcon->unix_ext = 1; /* Unix Extensions supported */
4013
4014 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004015 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004016 return;
4017 }
Steve French50c2f752007-07-13 00:33:32 +00004018
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004019 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00004020 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05004021 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00004022 /* check for reconnect case in which we do not
4023 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004024 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004025 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00004026 originally at mount time */
4027 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
4028 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004029 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
4030 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004031 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00004032 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004033 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004034 cifs_dbg(VFS, "possible reconnect error\n");
4035 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00004036 }
Steve French8af18972007-02-14 04:42:51 +00004037 }
Steve French50c2f752007-07-13 00:33:32 +00004038
Steve French6848b732011-05-26 18:38:54 +00004039 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004040 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00004041
Steve French8af18972007-02-14 04:42:51 +00004042 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00004043 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00004044 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004045 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004046 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004047 if (cifs_sb)
4048 cifs_sb->mnt_cifs_flags |=
4049 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00004050 }
4051
Steve French75865f8c2007-06-24 18:30:48 +00004052 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00004053 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004054 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004055 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004056 if (cifs_sb)
4057 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00004058 CIFS_MOUNT_POSIX_PATHS;
4059 }
Steve French50c2f752007-07-13 00:33:32 +00004060
Joe Perchesf96637b2013-05-04 22:12:25 -05004061 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00004062#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00004063 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004064 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004065 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004066 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004067 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004068 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004069 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004070 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004071 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004072 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004073 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004074 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004075 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004076 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00004077 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004078 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00004079 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004080 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00004081#endif /* CIFS_DEBUG2 */
4082 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00004083 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004084 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00004085 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05004086 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 +00004087
Steve French8af18972007-02-14 04:42:51 +00004088 }
4089 }
4090}
4091
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004092int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004093 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004094{
Jeff Layton2de970f2010-10-06 19:51:12 -04004095 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
4096
Al Viro2ced6f62011-06-17 09:20:04 -04004097 spin_lock_init(&cifs_sb->tlink_tree_lock);
4098 cifs_sb->tlink_tree = RB_ROOT;
4099
Steve Frenche8506d22019-02-28 21:32:15 -06004100 cifs_sb->bsize = pvolume_info->bsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004101 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004102 * Temporarily set r/wsize for matching superblock. If we end up using
4103 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004104 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004105 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004106 cifs_sb->wsize = pvolume_info->wsize;
4107
Steve French3b795212008-11-13 19:45:32 +00004108 cifs_sb->mnt_uid = pvolume_info->linux_uid;
4109 cifs_sb->mnt_gid = pvolume_info->linux_gid;
4110 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
4111 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Frank Sorensonf52aa792020-02-12 15:31:48 -06004112 cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05004113 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00004114
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304115 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004116 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304117
Aurelien Aptel83930722018-09-20 18:10:25 -07004118 if (pvolume_info->nodfs)
4119 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00004120 if (pvolume_info->noperm)
4121 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4122 if (pvolume_info->setuids)
4123 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05004124 if (pvolume_info->setuidfromacl)
4125 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00004126 if (pvolume_info->server_ino)
4127 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4128 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05004129 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
4130 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00004131 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4132 if (pvolume_info->no_xattr)
4133 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4134 if (pvolume_info->sfu_emul)
4135 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4136 if (pvolume_info->nobrl)
4137 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05004138 if (pvolume_info->nohandlecache)
4139 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00004140 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00004141 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00004142 if (pvolume_info->mand_lock)
4143 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00004144 if (pvolume_info->rwpidforward)
4145 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French412094a2019-06-24 02:01:42 -05004146 if (pvolume_info->mode_ace)
4147 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
Steve French3b795212008-11-13 19:45:32 +00004148 if (pvolume_info->cifs_acl)
4149 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004150 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004151 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004152 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
4153 }
4154 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004155 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004156 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
4157 }
Steve French3b795212008-11-13 19:45:32 +00004158 if (pvolume_info->override_uid)
4159 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
4160 if (pvolume_info->override_gid)
4161 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
4162 if (pvolume_info->dynperm)
4163 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05304164 if (pvolume_info->fsc)
4165 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04004166 if (pvolume_info->multiuser)
4167 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
4168 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05004169 if (pvolume_info->strict_io)
4170 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00004171 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004172 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00004173 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
4174 }
Steve French83bbfa72019-08-27 23:58:54 -05004175 if (pvolume_info->cache_ro) {
4176 cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4177 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
Steve French41e033f2019-08-30 02:12:41 -05004178 } else if (pvolume_info->cache_rw) {
4179 cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4180 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4181 CIFS_MOUNT_RW_CACHE);
Steve French83bbfa72019-08-27 23:58:54 -05004182 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004183 if (pvolume_info->mfsymlinks) {
4184 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05004185 /*
4186 * Our SFU ("Services for Unix" emulation does not allow
4187 * creating symlinks but does allow reading existing SFU
4188 * symlinks (it does allow both creating and reading SFU
4189 * style mknod and FIFOs though). When "mfsymlinks" and
4190 * "sfu" are both enabled at the same time, it allows
4191 * reading both types of symlinks, but will only create
4192 * them with mfsymlinks format. This allows better
4193 * Apple compatibility (probably better for Samba too)
4194 * while still recognizing old Windows style symlinks.
4195 */
4196 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004197 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05004198 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004199 }
Steve French3b795212008-11-13 19:45:32 +00004200
4201 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05004202 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004203
4204 if (pvolume_info->prepath) {
4205 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
4206 if (cifs_sb->prepath == NULL)
4207 return -ENOMEM;
4208 }
4209
4210 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004211}
4212
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004213void
4214cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004215{
Sean Finneyb9468452011-04-11 13:19:32 +00004216 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004217 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02004218 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00004219 kfree(volume_info->domainname);
4220 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004221 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004222}
4223
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004224void
4225cifs_cleanup_volume_info(struct smb_vol *volume_info)
4226{
4227 if (!volume_info)
4228 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004229 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004230 kfree(volume_info);
4231}
4232
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004233/* Release all succeed connections */
4234static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4235 unsigned int xid,
4236 struct TCP_Server_Info *server,
4237 struct cifs_ses *ses, struct cifs_tcon *tcon)
4238{
4239 int rc = 0;
4240
4241 if (tcon)
4242 cifs_put_tcon(tcon);
4243 else if (ses)
4244 cifs_put_smb_ses(ses);
4245 else if (server)
4246 cifs_put_tcp_session(server, 0);
4247 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4248 free_xid(xid);
4249}
4250
4251/* Get connections for tcp, ses and tcon */
4252static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4253 unsigned int *xid,
4254 struct TCP_Server_Info **nserver,
4255 struct cifs_ses **nses, struct cifs_tcon **ntcon)
4256{
4257 int rc = 0;
4258 struct TCP_Server_Info *server;
4259 struct cifs_ses *ses;
4260 struct cifs_tcon *tcon;
4261
4262 *nserver = NULL;
4263 *nses = NULL;
4264 *ntcon = NULL;
4265
4266 *xid = get_xid();
4267
4268 /* get a reference to a tcp session */
4269 server = cifs_get_tcp_session(vol);
4270 if (IS_ERR(server)) {
4271 rc = PTR_ERR(server);
4272 return rc;
4273 }
4274
4275 *nserver = server;
4276
4277 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
4278 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4279 else
4280 server->max_credits = vol->max_credits;
4281
4282 /* get a reference to a SMB session */
4283 ses = cifs_get_smb_ses(server, vol);
4284 if (IS_ERR(ses)) {
4285 rc = PTR_ERR(ses);
4286 return rc;
4287 }
4288
4289 *nses = ses;
4290
4291 if ((vol->persistent == true) && (!(ses->server->capabilities &
4292 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004293 cifs_server_dbg(VFS, "persistent handles not supported by server\n");
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004294 return -EOPNOTSUPP;
4295 }
4296
4297 /* search for existing tcon to this server share */
4298 tcon = cifs_get_tcon(ses, vol);
4299 if (IS_ERR(tcon)) {
4300 rc = PTR_ERR(tcon);
4301 return rc;
4302 }
4303
4304 *ntcon = tcon;
4305
4306 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4307 if (tcon->posix_extensions)
4308 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4309
4310 /* tell server which Unix caps we support */
4311 if (cap_unix(tcon->ses)) {
4312 /*
4313 * reset of caps checks mount to see if unix extensions disabled
4314 * for just this mount.
4315 */
4316 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4317 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4318 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4319 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4320 return -EACCES;
4321 } else
4322 tcon->unix_ext = 0; /* server does not support them */
4323
4324 /* do not care if a following call succeed - informational */
Steve French1981eba2019-08-29 22:33:38 -05004325 if (!tcon->pipe && server->ops->qfs_tcon) {
Amir Goldstein0f060932020-02-03 21:46:43 +02004326 server->ops->qfs_tcon(*xid, tcon, cifs_sb);
Steve French1981eba2019-08-29 22:33:38 -05004327 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4328 if (tcon->fsDevInfo.DeviceCharacteristics &
Steve French52870d52019-10-01 21:25:46 -05004329 cpu_to_le32(FILE_READ_ONLY_DEVICE))
Steve French1981eba2019-08-29 22:33:38 -05004330 cifs_dbg(VFS, "mounted to read only share\n");
Steve French41e033f2019-08-30 02:12:41 -05004331 else if ((cifs_sb->mnt_cifs_flags &
4332 CIFS_MOUNT_RW_CACHE) == 0)
Steve French1981eba2019-08-29 22:33:38 -05004333 cifs_dbg(VFS, "read only mount of RW share\n");
Steve French41e033f2019-08-30 02:12:41 -05004334 /* no need to log a RW mount of a typical RW share */
Steve French1981eba2019-08-29 22:33:38 -05004335 }
4336 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004337
4338 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4339 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4340
4341 return 0;
4342}
4343
4344static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4345 struct cifs_tcon *tcon)
4346{
4347 struct tcon_link *tlink;
4348
4349 /* hang the tcon off of the superblock */
4350 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4351 if (tlink == NULL)
4352 return -ENOMEM;
4353
4354 tlink->tl_uid = ses->linux_uid;
4355 tlink->tl_tcon = tcon;
4356 tlink->tl_time = jiffies;
4357 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4358 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4359
4360 cifs_sb->master_tlink = tlink;
4361 spin_lock(&cifs_sb->tlink_tree_lock);
4362 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4363 spin_unlock(&cifs_sb->tlink_tree_lock);
4364
4365 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4366 TLINK_IDLE_EXPIRE);
4367 return 0;
4368}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004369
Steve French2d6d5892009-04-09 00:36:44 +00004370#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004371/*
4372 * cifs_build_path_to_root returns full path to root when we do not have an
4373 * exiting connection (tcon)
4374 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004375static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004376build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004377 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004378{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004379 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004380 unsigned int pplen = useppath && vol->prepath ?
4381 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004382 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004383
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004384 if (unc_len > MAX_TREE_SIZE)
4385 return ERR_PTR(-EINVAL);
4386
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004387 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004388 if (full_path == NULL)
4389 return ERR_PTR(-ENOMEM);
4390
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004391 memcpy(full_path, vol->UNC, unc_len);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004392 pos = full_path + unc_len;
4393
4394 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004395 *pos = CIFS_DIR_SEP(cifs_sb);
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004396 memcpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004397 pos += pplen;
4398 }
4399
4400 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004401 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004402 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004403 return full_path;
4404}
Sean Finneydd613942011-04-11 13:19:30 +00004405
Paulo Alcantara1c780222018-11-14 16:24:03 -02004406/**
4407 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4408 *
Sean Finneydd613942011-04-11 13:19:30 +00004409 *
Sean Finney046462a2011-04-11 13:19:33 +00004410 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4411 * to a string containing updated options for the submount. Otherwise it
4412 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004413 *
4414 * Returns the rc from get_dfs_path to the caller, which can be used to
4415 * determine whether there were referrals.
4416 */
4417static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004418expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004419 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00004420 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00004421{
4422 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004423 struct dfs_info3_param referral = {0};
Sean Finneydd613942011-04-11 13:19:30 +00004424 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4425
Aurelien Aptel83930722018-09-20 18:10:25 -07004426 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4427 return -EREMOTE;
4428
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004429 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004430 if (IS_ERR(full_path))
4431 return PTR_ERR(full_path);
4432
4433 /* For DFS paths, skip the first '\' of the UNC */
4434 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4435
Paulo Alcantara1c780222018-11-14 16:24:03 -02004436 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4437 ref_path, &referral, NULL);
4438 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004439 char *fake_devname = NULL;
4440
4441 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004442 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004443 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004444 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004445
Sean Finneydd613942011-04-11 13:19:30 +00004446 if (IS_ERR(mdata)) {
4447 rc = PTR_ERR(mdata);
4448 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004449 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004450 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004451 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004452 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004453 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004454 kfree(fake_devname);
4455 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004456 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004457 }
4458 kfree(full_path);
4459 return rc;
4460}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004461
4462static inline int get_next_dfs_tgt(const char *path,
4463 struct dfs_cache_tgt_list *tgt_list,
4464 struct dfs_cache_tgt_iterator **tgt_it)
4465{
4466 if (!*tgt_it)
4467 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4468 else
4469 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4470 return !*tgt_it ? -EHOSTDOWN : 0;
4471}
4472
4473static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4474 struct smb_vol *fake_vol, struct smb_vol *vol)
4475{
4476 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4477 int len = strlen(tgt) + 2;
4478 char *new_unc;
4479
4480 new_unc = kmalloc(len, GFP_KERNEL);
4481 if (!new_unc)
4482 return -ENOMEM;
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +10004483 scnprintf(new_unc, len, "\\%s", tgt);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004484
4485 kfree(vol->UNC);
4486 vol->UNC = new_unc;
4487
4488 if (fake_vol->prepath) {
4489 kfree(vol->prepath);
4490 vol->prepath = fake_vol->prepath;
4491 fake_vol->prepath = NULL;
4492 }
4493 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4494
4495 return 0;
4496}
4497
4498static int setup_dfs_tgt_conn(const char *path,
4499 const struct dfs_cache_tgt_iterator *tgt_it,
4500 struct cifs_sb_info *cifs_sb,
4501 struct smb_vol *vol,
4502 unsigned int *xid,
4503 struct TCP_Server_Info **server,
4504 struct cifs_ses **ses,
4505 struct cifs_tcon **tcon)
4506{
4507 int rc;
4508 struct dfs_info3_param ref = {0};
4509 char *mdata = NULL, *fake_devname = NULL;
Steve Frenchd0959b02019-10-05 10:53:58 -05004510 struct smb_vol fake_vol = {NULL};
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004511
4512 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4513
4514 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4515 if (rc)
4516 return rc;
4517
4518 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4519 &fake_devname);
4520 free_dfs_info_param(&ref);
4521
4522 if (IS_ERR(mdata)) {
4523 rc = PTR_ERR(mdata);
4524 mdata = NULL;
4525 } else {
4526 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4527 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4528 false);
4529 }
4530 kfree(mdata);
4531 kfree(fake_devname);
4532
4533 if (!rc) {
4534 /*
4535 * We use a 'fake_vol' here because we need pass it down to the
4536 * mount_{get,put} functions to test connection against new DFS
4537 * targets.
4538 */
4539 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4540 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4541 tcon);
4542 if (!rc) {
4543 /*
4544 * We were able to connect to new target server.
4545 * Update current volume info with new target server.
4546 */
4547 rc = update_vol_info(tgt_it, &fake_vol, vol);
4548 }
4549 }
4550 cifs_cleanup_volume_info_contents(&fake_vol);
4551 return rc;
4552}
4553
4554static int mount_do_dfs_failover(const char *path,
4555 struct cifs_sb_info *cifs_sb,
4556 struct smb_vol *vol,
4557 struct cifs_ses *root_ses,
4558 unsigned int *xid,
4559 struct TCP_Server_Info **server,
4560 struct cifs_ses **ses,
4561 struct cifs_tcon **tcon)
4562{
4563 int rc;
4564 struct dfs_cache_tgt_list tgt_list;
4565 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4566
4567 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4568 return -EOPNOTSUPP;
4569
4570 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4571 if (rc)
4572 return rc;
4573
4574 for (;;) {
4575 /* Get next DFS target server - if any */
4576 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4577 if (rc)
4578 break;
4579 /* Connect to next DFS target */
4580 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4581 ses, tcon);
4582 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4583 break;
4584 }
4585 if (!rc) {
4586 /*
4587 * Update DFS target hint in DFS referral cache with the target
4588 * server we successfully reconnected to.
4589 */
4590 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4591 cifs_sb->local_nls,
4592 cifs_remap(cifs_sb), path,
4593 tgt_it);
4594 }
4595 dfs_cache_free_tgts(&tgt_list);
4596 return rc;
4597}
Steve French2d6d5892009-04-09 00:36:44 +00004598#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004599
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004600int
Jeff Layton04db79b2011-07-06 08:10:38 -04004601cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004602 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004604 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004605
Steve Frenchc7c137b2018-06-06 17:59:29 -05004606 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004607 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608
Jeff Layton7586b762008-12-01 18:41:49 -05004609 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004610 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004611 kfree(volume_info->username);
4612 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004613 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004615 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004617 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004618 /* In userspace mount helper we can get user name from alternate
4619 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004620 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004621 }
4622
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004624 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004625 /* load_nls_default cannot return null */
4626 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004628 volume_info->local_nls = load_nls(volume_info->iocharset);
4629 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004630 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004631 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004632 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633 }
4634 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004635
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004636 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004637}
4638
4639struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004640cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004641{
4642 int rc;
4643 struct smb_vol *volume_info;
4644
Jeff Layton6ee95422012-11-26 11:09:57 -05004645 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004646 if (!volume_info)
4647 return ERR_PTR(-ENOMEM);
4648
Steve Frenchc7c137b2018-06-06 17:59:29 -05004649 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004650 if (rc) {
4651 cifs_cleanup_volume_info(volume_info);
4652 volume_info = ERR_PTR(rc);
4653 }
4654
4655 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004656}
4657
Aurelien Aptela6b50582016-05-25 19:59:09 +02004658static int
4659cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4660 unsigned int xid,
4661 struct cifs_tcon *tcon,
4662 struct cifs_sb_info *cifs_sb,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004663 char *full_path,
4664 int added_treename)
Aurelien Aptela6b50582016-05-25 19:59:09 +02004665{
4666 int rc;
4667 char *s;
4668 char sep, tmp;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004669 int skip = added_treename ? 1 : 0;
Aurelien Aptela6b50582016-05-25 19:59:09 +02004670
4671 sep = CIFS_DIR_SEP(cifs_sb);
4672 s = full_path;
4673
4674 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4675 while (rc == 0) {
4676 /* skip separators */
4677 while (*s == sep)
4678 s++;
4679 if (!*s)
4680 break;
4681 /* next separator */
4682 while (*s && *s != sep)
4683 s++;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004684 /*
4685 * if the treename is added, we then have to skip the first
4686 * part within the separators
4687 */
4688 if (skip) {
4689 skip = 0;
4690 continue;
4691 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004692 /*
4693 * temporarily null-terminate the path at the end of
4694 * the current component
4695 */
4696 tmp = *s;
4697 *s = 0;
4698 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4699 full_path);
4700 *s = tmp;
4701 }
4702 return rc;
4703}
4704
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004705/*
4706 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4707 * otherwise 0.
4708 */
4709static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4710 const unsigned int xid,
4711 struct TCP_Server_Info *server,
4712 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004713{
Jeff Layton1daaae82012-03-21 06:30:40 -04004714 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004715 char *full_path;
4716
4717 if (!server->ops->is_path_accessible)
4718 return -EOPNOTSUPP;
4719
4720 /*
4721 * cifs_build_path_to_root works only when we have a valid tcon
4722 */
4723 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4724 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4725 if (full_path == NULL)
4726 return -ENOMEM;
4727
4728 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4729
4730 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4731 full_path);
4732 if (rc != 0 && rc != -EREMOTE) {
4733 kfree(full_path);
4734 return rc;
4735 }
4736
4737 if (rc != -EREMOTE) {
4738 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004739 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004740 if (rc != 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004741 cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004742 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4743 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4744 rc = 0;
4745 }
4746 }
4747
4748 kfree(full_path);
4749 return rc;
4750}
4751
4752#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004753static inline void set_root_tcon(struct cifs_sb_info *cifs_sb,
4754 struct cifs_tcon *tcon,
4755 struct cifs_tcon **root)
4756{
4757 spin_lock(&cifs_tcp_ses_lock);
4758 tcon->tc_count++;
4759 tcon->remap = cifs_remap(cifs_sb);
4760 spin_unlock(&cifs_tcp_ses_lock);
4761 *root = tcon;
4762}
4763
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004764int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4765{
4766 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004767 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004768 struct cifs_ses *ses;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004769 struct cifs_tcon *root_tcon = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004770 struct cifs_tcon *tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004771 struct TCP_Server_Info *server;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004772 char *root_path = NULL, *full_path = NULL;
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004773 char *old_mountdata, *origin_mountdata = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004774 int count;
Al Virodd854462011-06-17 08:24:42 -04004775
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004776 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4777 if (!rc && tcon) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004778 /* If not a standalone DFS root, then check if path is remote */
4779 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4780 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4781 NULL);
4782 if (rc) {
4783 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4784 if (!rc)
4785 goto out;
4786 if (rc != -EREMOTE)
4787 goto error;
4788 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004789 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004790 /*
4791 * If first DFS target server went offline and we failed to connect it,
4792 * server and ses pointers are NULL at this point, though we still have
4793 * chance to get a cached DFS referral in expand_dfs_referral() and
4794 * retry next target available in it.
4795 *
4796 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4797 * performed against DFS path and *no* requests will be sent to server
4798 * for any new DFS referrals. Hence it's safe to skip checking whether
4799 * server or ses ptr is NULL.
4800 */
4801 if (rc == -EACCES || rc == -EOPNOTSUPP)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004802 goto error;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004803
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004804 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4805 if (IS_ERR(root_path)) {
4806 rc = PTR_ERR(root_path);
4807 root_path = NULL;
4808 goto error;
4809 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004810
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004811 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4812 if (IS_ERR(full_path)) {
4813 rc = PTR_ERR(full_path);
4814 full_path = NULL;
4815 goto error;
4816 }
Sean Finneyc1508ca2011-04-11 13:19:31 +00004817 /*
4818 * Perform an unconditional check for whether there are DFS
4819 * referrals for this path without prefix, to provide support
4820 * for DFS referrals from w2k8 servers which don't seem to respond
4821 * with PATH_NOT_COVERED to requests that include the prefix.
4822 * Chase the referral if found, otherwise continue normally.
4823 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004824 old_mountdata = cifs_sb->mountdata;
4825 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004826
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004827 if (cifs_sb->mountdata == NULL) {
4828 rc = -ENOENT;
4829 goto error;
4830 }
4831
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004832 /* Save DFS root volume information for DFS refresh worker */
4833 origin_mountdata = kstrndup(cifs_sb->mountdata,
4834 strlen(cifs_sb->mountdata), GFP_KERNEL);
4835 if (!origin_mountdata) {
4836 rc = -ENOMEM;
4837 goto error;
4838 }
4839
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004840 if (cifs_sb->mountdata != old_mountdata) {
4841 /* If we were redirected, reconnect to new target server */
4842 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4843 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4844 }
4845 if (rc) {
4846 if (rc == -EACCES || rc == -EOPNOTSUPP)
4847 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004848 /* Perform DFS failover to any other DFS targets */
4849 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4850 &xid, &server, &ses, &tcon);
4851 if (rc)
4852 goto error;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004853 }
4854
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004855 kfree(root_path);
4856 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4857 if (IS_ERR(root_path)) {
4858 rc = PTR_ERR(root_path);
4859 root_path = NULL;
4860 goto error;
4861 }
4862 /* Cache out resolved root server */
4863 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4864 root_path + 1, NULL, NULL);
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004865 kfree(root_path);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004866 root_path = NULL;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004867
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004868 set_root_tcon(cifs_sb, tcon, &root_tcon);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004869
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004870 for (count = 1; ;) {
4871 if (!rc && tcon) {
4872 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4873 if (!rc || rc != -EREMOTE)
4874 break;
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004875 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004876 /*
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004877 * BB: when we implement proper loop detection,
4878 * we will remove this check. But now we need it
4879 * to prevent an indefinite loop if 'DFS tree' is
4880 * misconfigured (i.e. has loops).
Steve French6d3ea7e2012-11-28 22:34:41 -06004881 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004882 if (count++ > MAX_NESTED_LINKS) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004883 rc = -ELOOP;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004884 break;
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004885 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004886
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004887 kfree(full_path);
4888 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4889 if (IS_ERR(full_path)) {
4890 rc = PTR_ERR(full_path);
4891 full_path = NULL;
4892 break;
4893 }
4894
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004895 old_mountdata = cifs_sb->mountdata;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004896 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004897 true);
4898 if (rc)
4899 break;
Jeff Layton7b91e262009-07-23 15:22:30 -04004900
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004901 if (cifs_sb->mountdata != old_mountdata) {
4902 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4903 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4904 &tcon);
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004905 /*
4906 * Ensure that DFS referrals go through new root server.
4907 */
4908 if (!rc && tcon &&
4909 (tcon->share_flags & (SHI1005_FLAGS_DFS |
4910 SHI1005_FLAGS_DFS_ROOT))) {
4911 cifs_put_tcon(root_tcon);
4912 set_root_tcon(cifs_sb, tcon, &root_tcon);
4913 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004914 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004915 if (rc) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004916 if (rc == -EACCES || rc == -EOPNOTSUPP)
4917 break;
4918 /* Perform DFS failover to any other DFS targets */
4919 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4920 root_tcon->ses, &xid,
4921 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004922 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4923 !ses)
4924 goto error;
4925 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004926 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004927 cifs_put_tcon(root_tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004928
Jeff Layton9d002df2010-10-06 19:51:11 -04004929 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004930 goto error;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004931
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004932 spin_lock(&cifs_tcp_ses_lock);
4933 if (!tcon->dfs_path) {
4934 /* Save full path in new tcon to do failover when reconnecting tcons */
4935 tcon->dfs_path = full_path;
4936 full_path = NULL;
4937 tcon->remap = cifs_remap(cifs_sb);
4938 }
4939 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
YueHaibing2f0a6172018-12-18 01:34:39 +00004940 strlen(tcon->dfs_path),
4941 GFP_ATOMIC);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004942 if (!cifs_sb->origin_fullpath) {
4943 spin_unlock(&cifs_tcp_ses_lock);
4944 rc = -ENOMEM;
4945 goto error;
4946 }
4947 spin_unlock(&cifs_tcp_ses_lock);
4948
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004949 rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath);
Paulo Alcantarae511d312018-11-14 17:16:44 -02004950 if (rc) {
4951 kfree(cifs_sb->origin_fullpath);
4952 goto error;
4953 }
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004954 /*
4955 * After reconnecting to a different server, unique ids won't
4956 * match anymore, so we disable serverino. This prevents
4957 * dentry revalidation to think the dentry are stale (ESTALE).
4958 */
4959 cifs_autodisable_serverino(cifs_sb);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -03004960 /*
4961 * Force the use of prefix path to support failover on DFS paths that
4962 * resolve to targets that have different prefix paths.
4963 */
4964 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4965 kfree(cifs_sb->prepath);
4966 cifs_sb->prepath = vol->prepath;
4967 vol->prepath = NULL;
4968
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004969out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004970 free_xid(xid);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02004971 cifs_try_adding_channels(ses);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004972 return mount_setup_tlink(cifs_sb, ses, tcon);
4973
4974error:
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004975 kfree(full_path);
4976 kfree(root_path);
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004977 kfree(origin_mountdata);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004978 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004979 return rc;
4980}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004981#else
4982int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4983{
4984 int rc = 0;
4985 unsigned int xid;
4986 struct cifs_ses *ses;
4987 struct cifs_tcon *tcon;
4988 struct TCP_Server_Info *server;
4989
4990 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4991 if (rc)
4992 goto error;
4993
4994 if (tcon) {
4995 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4996 if (rc == -EREMOTE)
4997 rc = -EOPNOTSUPP;
4998 if (rc)
4999 goto error;
5000 }
5001
5002 free_xid(xid);
5003
5004 return mount_setup_tlink(cifs_sb, ses, tcon);
5005
5006error:
5007 mount_put_conns(cifs_sb, xid, server, ses, tcon);
5008 return rc;
5009}
5010#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005011
Jeff Layton8d1bca32011-06-11 21:17:10 -04005012/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01005013 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04005014 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005015int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04005016CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00005017 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 const struct nls_table *nls_codepage)
5019{
5020 struct smb_hdr *smb_buffer;
5021 struct smb_hdr *smb_buffer_response;
5022 TCONX_REQ *pSMB;
5023 TCONX_RSP *pSMBr;
5024 unsigned char *bcc_ptr;
5025 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05005026 int length;
5027 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028
5029 if (ses == NULL)
5030 return -EIO;
5031
5032 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00005033 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00005035
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036 smb_buffer_response = smb_buffer;
5037
5038 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
5039 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07005040
Pavel Shilovsky88257362012-05-23 14:01:59 +04005041 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042 smb_buffer->Uid = ses->Suid;
5043 pSMB = (TCONX_REQ *) smb_buffer;
5044 pSMBr = (TCONX_RSP *) smb_buffer_response;
5045
5046 pSMB->AndXCommand = 0xFF;
5047 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01005049 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08005050 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00005051 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08005052 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00005053 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08005054 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005055 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08005056 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
5057 specified as required (when that support is added to
5058 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00005059 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08005060 by Samba (not sure whether other servers allow
5061 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00005062#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04005063 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05005064 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05005065 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00005066 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05005067 SECMODE_PW_ENCRYPT ? true : false,
5068 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00005069 else
5070#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06005071 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05005072 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05005073 if (rc) {
5074 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
5075 __func__, rc);
5076 cifs_buf_release(smb_buffer);
5077 return rc;
5078 }
Steve Frencheeac8042006-01-13 21:34:58 -08005079
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005080 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005081 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00005082 /* must align unicode strings */
5083 *bcc_ptr = 0; /* null byte password */
5084 bcc_ptr++;
5085 }
Steve Frencheeac8042006-01-13 21:34:58 -08005086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087
Jeff Layton38d77c52013-05-26 07:01:00 -04005088 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005089 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
5090
5091 if (ses->capabilities & CAP_STATUS32) {
5092 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
5093 }
5094 if (ses->capabilities & CAP_DFS) {
5095 smb_buffer->Flags2 |= SMBFLG2_DFS;
5096 }
5097 if (ses->capabilities & CAP_UNICODE) {
5098 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
5099 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06005100 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00005101 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00005102 (/* server len*/ + 256 /* share len */), nls_codepage);
5103 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005104 bcc_ptr += 2; /* skip trailing null */
5105 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005106 strcpy(bcc_ptr, tree);
5107 bcc_ptr += strlen(tree) + 1;
5108 }
5109 strcpy(bcc_ptr, "?????");
5110 bcc_ptr += strlen("?????");
5111 bcc_ptr += 1;
5112 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00005113 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
5114 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115 pSMB->ByteCount = cpu_to_le16(count);
5116
Steve French133672e2007-11-13 22:41:37 +00005117 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05005118 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01005121 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00005122 bool is_unicode;
5123
Linus Torvalds1da177e2005-04-16 15:20:36 -07005124 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00005125 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126 tcon->tid = smb_buffer_response->Tid;
5127 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05005128 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005129 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00005130 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
5131 is_unicode = true;
5132 else
5133 is_unicode = false;
5134
Jeff Laytoncc20c032009-04-30 07:16:21 -04005135
Steve French50c2f752007-07-13 00:33:32 +00005136 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00005137 if (length == 3) {
5138 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
5139 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05005140 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01005141 tcon->ipc = true;
5142 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00005143 }
5144 } else if (length == 2) {
5145 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
5146 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05005147 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00005148 }
5149 }
Steve French50c2f752007-07-13 00:33:32 +00005150 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04005151 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05005152 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04005153
5154 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04005155 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06005156 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00005157 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04005158 nls_codepage);
5159
Joe Perchesf96637b2013-05-04 22:12:25 -05005160 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005161
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005162 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00005163 (smb_buffer_response->WordCount == 7))
5164 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00005165 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
5166 else
5167 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05005168 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169 }
5170
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00005171 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172 return rc;
5173}
5174
Al Viro2e32cf52013-10-03 12:53:37 -04005175static void delayed_free(struct rcu_head *p)
5176{
5177 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
5178 unload_nls(sbi->local_nls);
5179 kfree(sbi);
5180}
5181
Al Viro2a9b9952011-06-17 09:27:16 -04005182void
5183cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184{
Jeff Laytonb647c352010-10-28 11:16:44 -04005185 struct rb_root *root = &cifs_sb->tlink_tree;
5186 struct rb_node *node;
5187 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005188
Jeff Layton2de970f2010-10-06 19:51:12 -04005189 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
5190
Jeff Laytonb647c352010-10-28 11:16:44 -04005191 spin_lock(&cifs_sb->tlink_tree_lock);
5192 while ((node = rb_first(root))) {
5193 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5194 cifs_get_tlink(tlink);
5195 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5196 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00005197
Jeff Laytonb647c352010-10-28 11:16:44 -04005198 spin_unlock(&cifs_sb->tlink_tree_lock);
5199 cifs_put_tlink(tlink);
5200 spin_lock(&cifs_sb->tlink_tree_lock);
5201 }
5202 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005203
Al Virod757d712011-06-17 09:42:43 -04005204 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02005205 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005206#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02005207 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005208 kfree(cifs_sb->origin_fullpath);
5209#endif
Al Viro2e32cf52013-10-03 12:53:37 -04005210 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00005211}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005212
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005213int
5214cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215{
5216 int rc = 0;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005217 struct TCP_Server_Info *server = cifs_ses_server(ses);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005218
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005219 if (!server->ops->need_neg || !server->ops->negotiate)
5220 return -ENOSYS;
5221
Jeff Layton198b5682010-04-24 07:57:48 -04005222 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005223 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04005224 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005226 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005227 if (rc == 0) {
5228 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04005229 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04005230 server->tcpStatus = CifsGood;
5231 else
5232 rc = -EHOSTDOWN;
5233 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234 }
Steve French26b994f2008-08-06 05:11:33 +00005235
Jeff Layton198b5682010-04-24 07:57:48 -04005236 return rc;
5237}
Steve French26b994f2008-08-06 05:11:33 +00005238
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005239int
5240cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
5241 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04005242{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005243 int rc = -ENOSYS;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005244 struct TCP_Server_Info *server = cifs_ses_server(ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005245
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02005246 if (!ses->binding) {
5247 ses->capabilities = server->capabilities;
5248 if (linuxExtEnabled == 0)
5249 ses->capabilities &= (~server->vals->cap_unix);
5250
5251 if (ses->auth_key.response) {
5252 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
5253 ses->auth_key.response);
5254 kfree(ses->auth_key.response);
5255 ses->auth_key.response = NULL;
5256 ses->auth_key.len = 0;
5257 }
5258 }
Steve French20418ac2009-04-30 16:13:32 +00005259
Joe Perchesf96637b2013-05-04 22:12:25 -05005260 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00005261 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04005262
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005263 if (server->ops->sess_setup)
5264 rc = server->ops->sess_setup(xid, ses, nls_info);
5265
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05005266 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10005267 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05005268
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269 return rc;
5270}
5271
Jeff Layton8a8798a2012-01-17 16:09:15 -05005272static int
5273cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
5274{
Jeff Layton3f618222013-06-12 19:52:14 -05005275 vol->sectype = ses->sectype;
5276
5277 /* krb5 is special, since we don't need username or pw */
5278 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05005279 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05005280
5281 return cifs_set_cifscreds(vol, ses);
5282}
5283
Steve French96daf2b2011-05-27 04:34:02 +00005284static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005285cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04005286{
Jeff Layton8a8798a2012-01-17 16:09:15 -05005287 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00005288 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
5289 struct cifs_ses *ses;
5290 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04005291 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04005292
5293 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03005294 if (vol_info == NULL)
5295 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04005296
Jeff Layton9d002df2010-10-06 19:51:11 -04005297 vol_info->local_nls = cifs_sb->local_nls;
5298 vol_info->linux_uid = fsuid;
5299 vol_info->cred_uid = fsuid;
5300 vol_info->UNC = master_tcon->treeName;
5301 vol_info->retry = master_tcon->retry;
5302 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05005303 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04005304 vol_info->local_lease = master_tcon->local_lease;
5305 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04005306 vol_info->sectype = master_tcon->ses->sectype;
5307 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04005308
Jeff Layton8a8798a2012-01-17 16:09:15 -05005309 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
5310 if (rc) {
5311 tcon = ERR_PTR(rc);
5312 goto out;
5313 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005314
5315 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305316 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005317 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305318 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005319
5320 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
5321 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00005322 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07005323 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04005324 goto out;
5325 }
5326
5327 tcon = cifs_get_tcon(ses, vol_info);
5328 if (IS_ERR(tcon)) {
5329 cifs_put_smb_ses(ses);
5330 goto out;
5331 }
5332
Steve Frenchce558b02018-05-31 19:16:54 -05005333 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
5334 if (tcon->posix_extensions)
5335 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05005336
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005337 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04005338 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05005339
Jeff Layton9d002df2010-10-06 19:51:11 -04005340out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05005341 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01005342 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005343 kfree(vol_info);
5344
5345 return tcon;
5346}
5347
Steve French96daf2b2011-05-27 04:34:02 +00005348struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005349cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5350{
5351 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5352}
5353
Jeff Laytonb647c352010-10-28 11:16:44 -04005354/* find and return a tlink with given uid */
5355static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005356tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005357{
5358 struct rb_node *node = root->rb_node;
5359 struct tcon_link *tlink;
5360
5361 while (node) {
5362 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5363
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005364 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005365 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005366 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005367 node = node->rb_right;
5368 else
5369 return tlink;
5370 }
5371 return NULL;
5372}
5373
5374/* insert a tcon_link into the tree */
5375static void
5376tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5377{
5378 struct rb_node **new = &(root->rb_node), *parent = NULL;
5379 struct tcon_link *tlink;
5380
5381 while (*new) {
5382 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5383 parent = *new;
5384
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005385 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005386 new = &((*new)->rb_left);
5387 else
5388 new = &((*new)->rb_right);
5389 }
5390
5391 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5392 rb_insert_color(&new_tlink->tl_rbnode, root);
5393}
5394
Jeff Layton9d002df2010-10-06 19:51:11 -04005395/*
5396 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5397 * current task.
5398 *
5399 * If the superblock doesn't refer to a multiuser mount, then just return
5400 * the master tcon for the mount.
5401 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305402 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005403 * exists, then check to see if it's pending construction. If it is then wait
5404 * for construction to complete. Once it's no longer pending, check to see if
5405 * it failed and either return an error or retry construction, depending on
5406 * the timeout.
5407 *
5408 * If one doesn't exist then insert a new tcon_link struct into the tree and
5409 * try to construct a new one.
5410 */
5411struct tcon_link *
5412cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5413{
5414 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005415 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005416 struct tcon_link *tlink, *newtlink;
5417
5418 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5419 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5420
5421 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005422 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005423 if (tlink)
5424 cifs_get_tlink(tlink);
5425 spin_unlock(&cifs_sb->tlink_tree_lock);
5426
5427 if (tlink == NULL) {
5428 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5429 if (newtlink == NULL)
5430 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005431 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005432 newtlink->tl_tcon = ERR_PTR(-EACCES);
5433 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5434 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5435 cifs_get_tlink(newtlink);
5436
Jeff Layton9d002df2010-10-06 19:51:11 -04005437 spin_lock(&cifs_sb->tlink_tree_lock);
5438 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005439 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005440 if (tlink) {
5441 cifs_get_tlink(tlink);
5442 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005443 kfree(newtlink);
5444 goto wait_for_construction;
5445 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005446 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005447 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5448 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005449 } else {
5450wait_for_construction:
5451 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005452 TASK_INTERRUPTIBLE);
5453 if (ret) {
5454 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005455 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005456 }
5457
5458 /* if it's good, return it */
5459 if (!IS_ERR(tlink->tl_tcon))
5460 return tlink;
5461
5462 /* return error if we tried this already recently */
5463 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5464 cifs_put_tlink(tlink);
5465 return ERR_PTR(-EACCES);
5466 }
5467
5468 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5469 goto wait_for_construction;
5470 }
5471
5472 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5473 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5474 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5475
5476 if (IS_ERR(tlink->tl_tcon)) {
5477 cifs_put_tlink(tlink);
5478 return ERR_PTR(-EACCES);
5479 }
5480
5481 return tlink;
5482}
Jeff Layton2de970f2010-10-06 19:51:12 -04005483
5484/*
5485 * periodic workqueue job that scans tcon_tree for a superblock and closes
5486 * out tcons.
5487 */
5488static void
5489cifs_prune_tlinks(struct work_struct *work)
5490{
5491 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5492 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005493 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005494 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005495 struct rb_node *tmp;
5496 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005497
Jeff Laytonb647c352010-10-28 11:16:44 -04005498 /*
5499 * Because we drop the spinlock in the loop in order to put the tlink
5500 * it's not guarded against removal of links from the tree. The only
5501 * places that remove entries from the tree are this function and
5502 * umounts. Because this function is non-reentrant and is canceled
5503 * before umount can proceed, this is safe.
5504 */
5505 spin_lock(&cifs_sb->tlink_tree_lock);
5506 node = rb_first(root);
5507 while (node != NULL) {
5508 tmp = node;
5509 node = rb_next(tmp);
5510 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5511
5512 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5513 atomic_read(&tlink->tl_count) != 0 ||
5514 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5515 continue;
5516
5517 cifs_get_tlink(tlink);
5518 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5519 rb_erase(tmp, root);
5520
Jeff Layton2de970f2010-10-06 19:51:12 -04005521 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005522 cifs_put_tlink(tlink);
5523 spin_lock(&cifs_sb->tlink_tree_lock);
5524 }
5525 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005526
Jeff Laytonda472fc2012-03-23 14:40:53 -04005527 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005528 TLINK_IDLE_EXPIRE);
5529}