blob: 28268ed461b8286fb302ed732b47b2776b10209a [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);
Paulo Alcantara65303de2020-04-20 19:42:57 -03003378#ifdef CONFIG_CIFS_DFS_UPCALL
3379 if (tcon->dfs_path)
3380 continue;
3381#endif
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003382 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003383 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003384 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303385 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 return tcon;
3387 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303388 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 return NULL;
3390}
3391
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003392void
Steve French96daf2b2011-05-27 04:34:02 +00003393cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003394{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003395 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003396 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003397
Aurelien Aptelb327a712018-01-24 13:46:10 +01003398 /*
3399 * IPC tcon share the lifetime of their session and are
3400 * destroyed in the session put function
3401 */
3402 if (tcon == NULL || tcon->ipc)
3403 return;
3404
3405 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003406 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303407 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003408 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303409 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003410 return;
3411 }
3412
3413 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303414 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003415
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003416 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003417 if (ses->server->ops->tree_disconnect)
3418 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003419 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003420
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303421 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003422 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003423 cifs_put_smb_ses(ses);
3424}
3425
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003426/**
3427 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3428 *
3429 * - tcon refcount is the number of mount points using the tcon.
3430 * - ses refcount is the number of tcon using the session.
3431 *
3432 * 1. This function assumes it is being called from cifs_mount() where
3433 * we already got a session reference (ses refcount +1).
3434 *
3435 * 2. Since we're in the context of adding a mount point, the end
3436 * result should be either:
3437 *
3438 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3439 * its session refcount incremented (1 new tcon). This +1 was
3440 * already done in (1).
3441 *
3442 * b) an existing tcon with refcount+1 (add a mount point to it) and
3443 * identical ses refcount (no new tcon). Because of (1) we need to
3444 * decrement the ses refcount.
3445 */
Steve French96daf2b2011-05-27 04:34:02 +00003446static struct cifs_tcon *
3447cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003448{
3449 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003450 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003451
Steve French8b217fe2016-11-11 22:36:20 -06003452 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003453 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003454 /*
3455 * tcon has refcount already incremented but we need to
3456 * decrement extra ses reference gotten by caller (case b)
3457 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003458 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003459 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003460 return tcon;
3461 }
3462
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003463 if (!ses->server->ops->tree_connect) {
3464 rc = -ENOSYS;
3465 goto out_fail;
3466 }
3467
Jeff Laytond00c28d2010-04-24 07:57:44 -04003468 tcon = tconInfoAlloc();
3469 if (tcon == NULL) {
3470 rc = -ENOMEM;
3471 goto out_fail;
3472 }
3473
Steve French8b217fe2016-11-11 22:36:20 -06003474 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003475 if (ses->server->vals->protocol_id == 0) {
3476 cifs_dbg(VFS,
3477 "Use SMB2 or later for snapshot mount option\n");
3478 rc = -EOPNOTSUPP;
3479 goto out_fail;
3480 } else
3481 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003482 }
3483
Steve Frenchca567eb2019-03-29 16:31:07 -05003484 if (volume_info->handle_timeout) {
3485 if (ses->server->vals->protocol_id == 0) {
3486 cifs_dbg(VFS,
3487 "Use SMB2.1 or later for handle timeout option\n");
3488 rc = -EOPNOTSUPP;
3489 goto out_fail;
3490 } else
3491 tcon->handle_timeout = volume_info->handle_timeout;
3492 }
3493
Jeff Laytond00c28d2010-04-24 07:57:44 -04003494 tcon->ses = ses;
3495 if (volume_info->password) {
3496 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3497 if (!tcon->password) {
3498 rc = -ENOMEM;
3499 goto out_fail;
3500 }
3501 }
3502
Steve French23657ad2018-04-22 15:14:58 -05003503 if (volume_info->seal) {
3504 if (ses->server->vals->protocol_id == 0) {
3505 cifs_dbg(VFS,
3506 "SMB3 or later required for encryption\n");
3507 rc = -EOPNOTSUPP;
3508 goto out_fail;
3509 } else if (tcon->ses->server->capabilities &
3510 SMB2_GLOBAL_CAP_ENCRYPTION)
3511 tcon->seal = true;
3512 else {
3513 cifs_dbg(VFS, "Encryption is not supported on share\n");
3514 rc = -EOPNOTSUPP;
3515 goto out_fail;
3516 }
3517 }
3518
Steve French8505c8b2018-06-18 14:01:59 -05003519 if (volume_info->linux_ext) {
3520 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003521 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003522 printk_once(KERN_WARNING
3523 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003524 } else {
3525 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3526 rc = -EOPNOTSUPP;
3527 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003528 }
Steve Frenchb3266142018-05-20 23:41:10 -05003529 }
Steve Frenchb3266142018-05-20 23:41:10 -05003530
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003531 /*
3532 * BB Do we need to wrap session_mutex around this TCon call and Unix
3533 * SetFS as we do on SessSetup and reconnect?
3534 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003535 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003536 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3537 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003538 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003539 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003540 if (rc)
3541 goto out_fail;
3542
Steve Frenchb618f002015-11-03 09:15:03 -06003543 tcon->use_persistent = false;
3544 /* check if SMB2 or later, CIFS does not support persistent handles */
3545 if (volume_info->persistent) {
3546 if (ses->server->vals->protocol_id == 0) {
3547 cifs_dbg(VFS,
3548 "SMB3 or later required for persistent handles\n");
3549 rc = -EOPNOTSUPP;
3550 goto out_fail;
3551 } else if (ses->server->capabilities &
3552 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3553 tcon->use_persistent = true;
3554 else /* persistent handles requested but not supported */ {
3555 cifs_dbg(VFS,
3556 "Persistent handles not supported on share\n");
3557 rc = -EOPNOTSUPP;
3558 goto out_fail;
3559 }
3560 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3561 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3562 && (volume_info->nopersistent == false)) {
3563 cifs_dbg(FYI, "enabling persistent handles\n");
3564 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003565 } else if (volume_info->resilient) {
3566 if (ses->server->vals->protocol_id == 0) {
3567 cifs_dbg(VFS,
3568 "SMB2.1 or later required for resilient handles\n");
3569 rc = -EOPNOTSUPP;
3570 goto out_fail;
3571 }
3572 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003573 }
3574
Steve Frenchcae53f72019-09-03 17:49:46 -05003575 /* If the user really knows what they are doing they can override */
3576 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3577 if (volume_info->cache_ro)
3578 cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3579 else if (volume_info->cache_rw)
3580 cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3581 }
3582
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003583 /*
3584 * We can have only one retry value for a connection to a share so for
3585 * resources mounted more than once to the same server share the last
3586 * value passed in for the retry flag is used.
3587 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003588 tcon->retry = volume_info->retry;
3589 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003590 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003591 tcon->local_lease = volume_info->local_lease;
Steve French3e7a02d2019-09-11 21:46:20 -05003592 tcon->no_lease = volume_info->no_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003593 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003594
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303595 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003596 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303597 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003598
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303599 cifs_fscache_get_super_cookie(tcon);
3600
Jeff Laytond00c28d2010-04-24 07:57:44 -04003601 return tcon;
3602
3603out_fail:
3604 tconInfoFree(tcon);
3605 return ERR_PTR(rc);
3606}
3607
Jeff Layton9d002df2010-10-06 19:51:11 -04003608void
3609cifs_put_tlink(struct tcon_link *tlink)
3610{
3611 if (!tlink || IS_ERR(tlink))
3612 return;
3613
3614 if (!atomic_dec_and_test(&tlink->tl_count) ||
3615 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3616 tlink->tl_time = jiffies;
3617 return;
3618 }
3619
3620 if (!IS_ERR(tlink_tcon(tlink)))
3621 cifs_put_tcon(tlink_tcon(tlink));
3622 kfree(tlink);
3623 return;
3624}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003625
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003626static int
3627compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3628{
3629 struct cifs_sb_info *old = CIFS_SB(sb);
3630 struct cifs_sb_info *new = mnt_data->cifs_sb;
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003631 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3632 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003633
3634 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3635 return 0;
3636
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003637 if (old->mnt_cifs_serverino_autodisabled)
3638 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3639
3640 if (oldflags != newflags)
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003641 return 0;
3642
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003643 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003644 * We want to share sb only if we don't specify an r/wsize or
3645 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003646 */
3647 if (new->wsize && new->wsize < old->wsize)
3648 return 0;
3649
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003650 if (new->rsize && new->rsize < old->rsize)
3651 return 0;
3652
Eric W. Biederman1f682332013-02-06 01:20:20 -08003653 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003654 return 0;
3655
3656 if (old->mnt_file_mode != new->mnt_file_mode ||
3657 old->mnt_dir_mode != new->mnt_dir_mode)
3658 return 0;
3659
3660 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3661 return 0;
3662
3663 if (old->actimeo != new->actimeo)
3664 return 0;
3665
3666 return 1;
3667}
3668
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003669static int
3670match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3671{
3672 struct cifs_sb_info *old = CIFS_SB(sb);
3673 struct cifs_sb_info *new = mnt_data->cifs_sb;
Ronnie Sahlbergfe129262020-01-22 11:07:56 +10003674 bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3675 old->prepath;
3676 bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3677 new->prepath;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003678
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003679 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003680 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003681 else if (!old_set && !new_set)
3682 return 1;
3683
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003684 return 0;
3685}
3686
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003687int
3688cifs_match_super(struct super_block *sb, void *data)
3689{
3690 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3691 struct smb_vol *volume_info;
3692 struct cifs_sb_info *cifs_sb;
3693 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003694 struct cifs_ses *ses;
3695 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003696 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003697 int rc = 0;
3698
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003699 spin_lock(&cifs_tcp_ses_lock);
3700 cifs_sb = CIFS_SB(sb);
3701 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3702 if (IS_ERR(tlink)) {
3703 spin_unlock(&cifs_tcp_ses_lock);
3704 return rc;
3705 }
3706 tcon = tlink_tcon(tlink);
3707 ses = tcon->ses;
3708 tcp_srv = ses->server;
3709
3710 volume_info = mnt_data->vol;
3711
Jeff Layton9fa114f2012-11-26 11:09:57 -05003712 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003713 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003714 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003715 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003716 rc = 0;
3717 goto out;
3718 }
3719
3720 rc = compare_mount_options(sb, mnt_data);
3721out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003722 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003723 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003724 return rc;
3725}
3726
Jeff Layton09e50d52008-07-23 10:11:19 -04003727#ifdef CONFIG_DEBUG_LOCK_ALLOC
3728static struct lock_class_key cifs_key[2];
3729static struct lock_class_key cifs_slock_key[2];
3730
3731static inline void
3732cifs_reclassify_socket4(struct socket *sock)
3733{
3734 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003735 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003736 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3737 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3738}
3739
3740static inline void
3741cifs_reclassify_socket6(struct socket *sock)
3742{
3743 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003744 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003745 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3746 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3747}
3748#else
3749static inline void
3750cifs_reclassify_socket4(struct socket *sock)
3751{
3752}
3753
3754static inline void
3755cifs_reclassify_socket6(struct socket *sock)
3756{
3757}
3758#endif
3759
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003761static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762{
Steve French50c2f752007-07-13 00:33:32 +00003763 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764
Steve French50c2f752007-07-13 00:33:32 +00003765 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766 /* mask a nibble at a time and encode */
3767 target[j] = 'A' + (0x0F & (source[i] >> 4));
3768 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003769 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 }
3771
3772}
3773
Ben Greear3eb9a882010-09-01 17:06:02 -07003774static int
3775bind_socket(struct TCP_Server_Info *server)
3776{
3777 int rc = 0;
3778 if (server->srcaddr.ss_family != AF_UNSPEC) {
3779 /* Bind to the specified local IP address */
3780 struct socket *socket = server->ssocket;
3781 rc = socket->ops->bind(socket,
3782 (struct sockaddr *) &server->srcaddr,
3783 sizeof(server->srcaddr));
3784 if (rc < 0) {
3785 struct sockaddr_in *saddr4;
3786 struct sockaddr_in6 *saddr6;
3787 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3788 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3789 if (saddr6->sin6_family == AF_INET6)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003790 cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003791 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003792 else
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003793 cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003794 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003795 }
3796 }
3797 return rc;
3798}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799
3800static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003801ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802{
3803 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003804 /*
3805 * some servers require RFC1001 sessinit before sending
3806 * negprot - BB check reconnection in case where second
3807 * sessinit is sent but no second negprot
3808 */
3809 struct rfc1002_session_packet *ses_init_buf;
3810 struct smb_hdr *smb_buf;
3811 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3812 GFP_KERNEL);
3813 if (ses_init_buf) {
3814 ses_init_buf->trailer.session_req.called_len = 32;
3815
Colin Ian King997152f2016-01-25 16:25:54 +00003816 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003817 rfc1002mangle(ses_init_buf->trailer.
3818 session_req.called_name,
3819 server->server_RFC1001_name,
3820 RFC1001_NAME_LEN_WITH_NULL);
3821 else
3822 rfc1002mangle(ses_init_buf->trailer.
3823 session_req.called_name,
3824 DEFAULT_CIFS_CALLED_NAME,
3825 RFC1001_NAME_LEN_WITH_NULL);
3826
3827 ses_init_buf->trailer.session_req.calling_len = 32;
3828
3829 /*
3830 * calling name ends in null (byte 16) from old smb
3831 * convention.
3832 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003833 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003834 rfc1002mangle(ses_init_buf->trailer.
3835 session_req.calling_name,
3836 server->workstation_RFC1001_name,
3837 RFC1001_NAME_LEN_WITH_NULL);
3838 else
3839 rfc1002mangle(ses_init_buf->trailer.
3840 session_req.calling_name,
3841 "LINUX_CIFS_CLNT",
3842 RFC1001_NAME_LEN_WITH_NULL);
3843
3844 ses_init_buf->trailer.session_req.scope1 = 0;
3845 ses_init_buf->trailer.session_req.scope2 = 0;
3846 smb_buf = (struct smb_hdr *)ses_init_buf;
3847
3848 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003849 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003850 rc = smb_send(server, smb_buf, 0x44);
3851 kfree(ses_init_buf);
3852 /*
3853 * RFC1001 layer in at least one server
3854 * requires very short break before negprot
3855 * presumably because not expecting negprot
3856 * to follow so fast. This is a simple
3857 * solution that works without
3858 * complicating the code and causes no
3859 * significant slowing down on mount
3860 * for everyone else
3861 */
3862 usleep_range(1000, 2000);
3863 }
3864 /*
3865 * else the negprot may still work without this
3866 * even though malloc failed
3867 */
3868
3869 return rc;
3870}
3871
3872static int
3873generic_ip_connect(struct TCP_Server_Info *server)
3874{
3875 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003876 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003877 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003878 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003879 struct sockaddr *saddr;
3880
3881 saddr = (struct sockaddr *) &server->dstaddr;
3882
3883 if (server->dstaddr.ss_family == AF_INET6) {
3884 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3885 slen = sizeof(struct sockaddr_in6);
3886 sfamily = AF_INET6;
3887 } else {
3888 sport = ((struct sockaddr_in *) saddr)->sin_port;
3889 slen = sizeof(struct sockaddr_in);
3890 sfamily = AF_INET;
3891 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003893 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003894 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3895 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 if (rc < 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003897 cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003898 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003901
3902 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003903 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003904 server->ssocket = socket;
3905 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003906 if (sfamily == AF_INET6)
3907 cifs_reclassify_socket6(socket);
3908 else
3909 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 }
3911
Ben Greear3eb9a882010-09-01 17:06:02 -07003912 rc = bind_socket(server);
3913 if (rc < 0)
3914 return rc;
3915
Jeff Laytond5c56052008-12-01 18:42:33 -05003916 /*
3917 * Eventually check for other socket options to change from
3918 * the default. sock_setsockopt not used because it expects
3919 * user space buffer
3920 */
3921 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003922 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003923
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003924 /* make the bufsizes depend on wsize/rsize and max requests */
3925 if (server->noautotune) {
3926 if (socket->sk->sk_sndbuf < (200 * 1024))
3927 socket->sk->sk_sndbuf = 200 * 1024;
3928 if (socket->sk->sk_rcvbuf < (140 * 1024))
3929 socket->sk->sk_rcvbuf = 140 * 1024;
3930 }
3931
Steve French6a5fa2362010-01-01 01:28:43 +00003932 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003933 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003934 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3935 (char *)&val, sizeof(val));
3936 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003937 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3938 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003939 }
3940
Joe Perchesf96637b2013-05-04 22:12:25 -05003941 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003942 socket->sk->sk_sndbuf,
3943 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3944
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003945 rc = socket->ops->connect(socket, saddr, slen,
3946 server->noblockcnt ? O_NONBLOCK : 0);
Paulo Alcantara (SUSE)d532cc72019-10-10 12:31:58 -03003947 /*
3948 * When mounting SMB root file systems, we do not want to block in
3949 * connect. Otherwise bail out and then let cifs_reconnect() perform
3950 * reconnect failover - if possible.
3951 */
3952 if (server->noblockcnt && rc == -EINPROGRESS)
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003953 rc = 0;
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003954 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003955 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003956 sock_release(socket);
3957 server->ssocket = NULL;
3958 return rc;
3959 }
3960
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003961 if (sport == htons(RFC1001_PORT))
3962 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003963
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 return rc;
3965}
3966
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003967static int
3968ip_connect(struct TCP_Server_Info *server)
3969{
Steve French6da97912011-03-13 18:55:55 +00003970 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003971 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3972 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3973
3974 if (server->dstaddr.ss_family == AF_INET6)
3975 sport = &addr6->sin6_port;
3976 else
3977 sport = &addr->sin_port;
3978
3979 if (*sport == 0) {
3980 int rc;
3981
3982 /* try with 445 port at first */
3983 *sport = htons(CIFS_PORT);
3984
3985 rc = generic_ip_connect(server);
3986 if (rc >= 0)
3987 return rc;
3988
3989 /* if it failed, try with 139 port */
3990 *sport = htons(RFC1001_PORT);
3991 }
3992
3993 return generic_ip_connect(server);
3994}
3995
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003996void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003997 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003998{
3999 /* if we are reconnecting then should we check to see if
4000 * any requested capabilities changed locally e.g. via
4001 * remount but we can not do much about it here
4002 * if they have (even if we could detect it by the following)
4003 * Perhaps we could add a backpointer to array of sb from tcon
4004 * or if we change to make all sb to same share the same
4005 * sb as NFS - then we only have one backpointer to sb.
4006 * What if we wanted to mount the server share twice once with
4007 * and once without posixacls or posix paths? */
4008 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00004009
Steve Frenchc18c8422007-07-18 23:21:09 +00004010 if (vol_info && vol_info->no_linux_ext) {
4011 tcon->fsUnixInfo.Capability = 0;
4012 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05004013 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004014 return;
4015 } else if (vol_info)
4016 tcon->unix_ext = 1; /* Unix Extensions supported */
4017
4018 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004019 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004020 return;
4021 }
Steve French50c2f752007-07-13 00:33:32 +00004022
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004023 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00004024 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05004025 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00004026 /* check for reconnect case in which we do not
4027 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004028 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004029 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00004030 originally at mount time */
4031 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
4032 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004033 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
4034 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004035 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00004036 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004037 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004038 cifs_dbg(VFS, "possible reconnect error\n");
4039 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00004040 }
Steve French8af18972007-02-14 04:42:51 +00004041 }
Steve French50c2f752007-07-13 00:33:32 +00004042
Steve French6848b732011-05-26 18:38:54 +00004043 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004044 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00004045
Steve French8af18972007-02-14 04:42:51 +00004046 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00004047 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00004048 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004049 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004050 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004051 if (cifs_sb)
4052 cifs_sb->mnt_cifs_flags |=
4053 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00004054 }
4055
Steve French75865f8c2007-06-24 18:30:48 +00004056 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00004057 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004058 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004059 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004060 if (cifs_sb)
4061 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00004062 CIFS_MOUNT_POSIX_PATHS;
4063 }
Steve French50c2f752007-07-13 00:33:32 +00004064
Joe Perchesf96637b2013-05-04 22:12:25 -05004065 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00004066#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00004067 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004068 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004069 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004070 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004071 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004072 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004073 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004074 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004075 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004076 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004077 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004078 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004079 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004080 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00004081 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004082 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00004083 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004084 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00004085#endif /* CIFS_DEBUG2 */
4086 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00004087 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004088 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00004089 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05004090 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 +00004091
Steve French8af18972007-02-14 04:42:51 +00004092 }
4093 }
4094}
4095
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004096int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004097 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004098{
Jeff Layton2de970f2010-10-06 19:51:12 -04004099 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
4100
Al Viro2ced6f62011-06-17 09:20:04 -04004101 spin_lock_init(&cifs_sb->tlink_tree_lock);
4102 cifs_sb->tlink_tree = RB_ROOT;
4103
Steve Frenche8506d22019-02-28 21:32:15 -06004104 cifs_sb->bsize = pvolume_info->bsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004105 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004106 * Temporarily set r/wsize for matching superblock. If we end up using
4107 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004108 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004109 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004110 cifs_sb->wsize = pvolume_info->wsize;
4111
Steve French3b795212008-11-13 19:45:32 +00004112 cifs_sb->mnt_uid = pvolume_info->linux_uid;
4113 cifs_sb->mnt_gid = pvolume_info->linux_gid;
4114 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
4115 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Frank Sorensonf52aa792020-02-12 15:31:48 -06004116 cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05004117 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00004118
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304119 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004120 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304121
Aurelien Aptel83930722018-09-20 18:10:25 -07004122 if (pvolume_info->nodfs)
4123 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00004124 if (pvolume_info->noperm)
4125 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4126 if (pvolume_info->setuids)
4127 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05004128 if (pvolume_info->setuidfromacl)
4129 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00004130 if (pvolume_info->server_ino)
4131 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4132 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05004133 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
4134 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00004135 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4136 if (pvolume_info->no_xattr)
4137 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4138 if (pvolume_info->sfu_emul)
4139 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4140 if (pvolume_info->nobrl)
4141 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05004142 if (pvolume_info->nohandlecache)
4143 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00004144 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00004145 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00004146 if (pvolume_info->mand_lock)
4147 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00004148 if (pvolume_info->rwpidforward)
4149 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French412094a2019-06-24 02:01:42 -05004150 if (pvolume_info->mode_ace)
4151 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
Steve French3b795212008-11-13 19:45:32 +00004152 if (pvolume_info->cifs_acl)
4153 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004154 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004155 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004156 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
4157 }
4158 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004159 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004160 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
4161 }
Steve French3b795212008-11-13 19:45:32 +00004162 if (pvolume_info->override_uid)
4163 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
4164 if (pvolume_info->override_gid)
4165 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
4166 if (pvolume_info->dynperm)
4167 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05304168 if (pvolume_info->fsc)
4169 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04004170 if (pvolume_info->multiuser)
4171 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
4172 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05004173 if (pvolume_info->strict_io)
4174 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00004175 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004176 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00004177 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
4178 }
Steve French83bbfa72019-08-27 23:58:54 -05004179 if (pvolume_info->cache_ro) {
4180 cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4181 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
Steve French41e033f2019-08-30 02:12:41 -05004182 } else if (pvolume_info->cache_rw) {
4183 cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4184 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4185 CIFS_MOUNT_RW_CACHE);
Steve French83bbfa72019-08-27 23:58:54 -05004186 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004187 if (pvolume_info->mfsymlinks) {
4188 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05004189 /*
4190 * Our SFU ("Services for Unix" emulation does not allow
4191 * creating symlinks but does allow reading existing SFU
4192 * symlinks (it does allow both creating and reading SFU
4193 * style mknod and FIFOs though). When "mfsymlinks" and
4194 * "sfu" are both enabled at the same time, it allows
4195 * reading both types of symlinks, but will only create
4196 * them with mfsymlinks format. This allows better
4197 * Apple compatibility (probably better for Samba too)
4198 * while still recognizing old Windows style symlinks.
4199 */
4200 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004201 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05004202 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004203 }
Steve French3b795212008-11-13 19:45:32 +00004204
4205 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05004206 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004207
4208 if (pvolume_info->prepath) {
4209 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
4210 if (cifs_sb->prepath == NULL)
4211 return -ENOMEM;
4212 }
4213
4214 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004215}
4216
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004217void
4218cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004219{
Sean Finneyb9468452011-04-11 13:19:32 +00004220 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004221 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02004222 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00004223 kfree(volume_info->domainname);
4224 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004225 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004226}
4227
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004228void
4229cifs_cleanup_volume_info(struct smb_vol *volume_info)
4230{
4231 if (!volume_info)
4232 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004233 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004234 kfree(volume_info);
4235}
4236
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004237/* Release all succeed connections */
4238static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4239 unsigned int xid,
4240 struct TCP_Server_Info *server,
4241 struct cifs_ses *ses, struct cifs_tcon *tcon)
4242{
4243 int rc = 0;
4244
4245 if (tcon)
4246 cifs_put_tcon(tcon);
4247 else if (ses)
4248 cifs_put_smb_ses(ses);
4249 else if (server)
4250 cifs_put_tcp_session(server, 0);
4251 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4252 free_xid(xid);
4253}
4254
4255/* Get connections for tcp, ses and tcon */
4256static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4257 unsigned int *xid,
4258 struct TCP_Server_Info **nserver,
4259 struct cifs_ses **nses, struct cifs_tcon **ntcon)
4260{
4261 int rc = 0;
4262 struct TCP_Server_Info *server;
4263 struct cifs_ses *ses;
4264 struct cifs_tcon *tcon;
4265
4266 *nserver = NULL;
4267 *nses = NULL;
4268 *ntcon = NULL;
4269
4270 *xid = get_xid();
4271
4272 /* get a reference to a tcp session */
4273 server = cifs_get_tcp_session(vol);
4274 if (IS_ERR(server)) {
4275 rc = PTR_ERR(server);
4276 return rc;
4277 }
4278
4279 *nserver = server;
4280
4281 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
4282 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4283 else
4284 server->max_credits = vol->max_credits;
4285
4286 /* get a reference to a SMB session */
4287 ses = cifs_get_smb_ses(server, vol);
4288 if (IS_ERR(ses)) {
4289 rc = PTR_ERR(ses);
4290 return rc;
4291 }
4292
4293 *nses = ses;
4294
4295 if ((vol->persistent == true) && (!(ses->server->capabilities &
4296 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004297 cifs_server_dbg(VFS, "persistent handles not supported by server\n");
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004298 return -EOPNOTSUPP;
4299 }
4300
4301 /* search for existing tcon to this server share */
4302 tcon = cifs_get_tcon(ses, vol);
4303 if (IS_ERR(tcon)) {
4304 rc = PTR_ERR(tcon);
4305 return rc;
4306 }
4307
4308 *ntcon = tcon;
4309
4310 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4311 if (tcon->posix_extensions)
4312 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4313
4314 /* tell server which Unix caps we support */
4315 if (cap_unix(tcon->ses)) {
4316 /*
4317 * reset of caps checks mount to see if unix extensions disabled
4318 * for just this mount.
4319 */
4320 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4321 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4322 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4323 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4324 return -EACCES;
4325 } else
4326 tcon->unix_ext = 0; /* server does not support them */
4327
4328 /* do not care if a following call succeed - informational */
Steve French1981eba2019-08-29 22:33:38 -05004329 if (!tcon->pipe && server->ops->qfs_tcon) {
Amir Goldstein0f060932020-02-03 21:46:43 +02004330 server->ops->qfs_tcon(*xid, tcon, cifs_sb);
Steve French1981eba2019-08-29 22:33:38 -05004331 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4332 if (tcon->fsDevInfo.DeviceCharacteristics &
Steve French52870d52019-10-01 21:25:46 -05004333 cpu_to_le32(FILE_READ_ONLY_DEVICE))
Steve French1981eba2019-08-29 22:33:38 -05004334 cifs_dbg(VFS, "mounted to read only share\n");
Steve French41e033f2019-08-30 02:12:41 -05004335 else if ((cifs_sb->mnt_cifs_flags &
4336 CIFS_MOUNT_RW_CACHE) == 0)
Steve French1981eba2019-08-29 22:33:38 -05004337 cifs_dbg(VFS, "read only mount of RW share\n");
Steve French41e033f2019-08-30 02:12:41 -05004338 /* no need to log a RW mount of a typical RW share */
Steve French1981eba2019-08-29 22:33:38 -05004339 }
4340 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004341
4342 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4343 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4344
4345 return 0;
4346}
4347
4348static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4349 struct cifs_tcon *tcon)
4350{
4351 struct tcon_link *tlink;
4352
4353 /* hang the tcon off of the superblock */
4354 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4355 if (tlink == NULL)
4356 return -ENOMEM;
4357
4358 tlink->tl_uid = ses->linux_uid;
4359 tlink->tl_tcon = tcon;
4360 tlink->tl_time = jiffies;
4361 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4362 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4363
4364 cifs_sb->master_tlink = tlink;
4365 spin_lock(&cifs_sb->tlink_tree_lock);
4366 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4367 spin_unlock(&cifs_sb->tlink_tree_lock);
4368
4369 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4370 TLINK_IDLE_EXPIRE);
4371 return 0;
4372}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004373
Steve French2d6d5892009-04-09 00:36:44 +00004374#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004375/*
4376 * cifs_build_path_to_root returns full path to root when we do not have an
4377 * exiting connection (tcon)
4378 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004379static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004380build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004381 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004382{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004383 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004384 unsigned int pplen = useppath && vol->prepath ?
4385 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004386 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004387
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004388 if (unc_len > MAX_TREE_SIZE)
4389 return ERR_PTR(-EINVAL);
4390
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004391 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004392 if (full_path == NULL)
4393 return ERR_PTR(-ENOMEM);
4394
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004395 memcpy(full_path, vol->UNC, unc_len);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004396 pos = full_path + unc_len;
4397
4398 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004399 *pos = CIFS_DIR_SEP(cifs_sb);
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004400 memcpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004401 pos += pplen;
4402 }
4403
4404 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004405 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004406 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004407 return full_path;
4408}
Sean Finneydd613942011-04-11 13:19:30 +00004409
Paulo Alcantara1c780222018-11-14 16:24:03 -02004410/**
4411 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4412 *
Sean Finneydd613942011-04-11 13:19:30 +00004413 *
Sean Finney046462a2011-04-11 13:19:33 +00004414 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4415 * to a string containing updated options for the submount. Otherwise it
4416 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004417 *
4418 * Returns the rc from get_dfs_path to the caller, which can be used to
4419 * determine whether there were referrals.
4420 */
4421static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004422expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004423 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00004424 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00004425{
4426 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004427 struct dfs_info3_param referral = {0};
Sean Finneydd613942011-04-11 13:19:30 +00004428 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4429
Aurelien Aptel83930722018-09-20 18:10:25 -07004430 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4431 return -EREMOTE;
4432
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004433 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004434 if (IS_ERR(full_path))
4435 return PTR_ERR(full_path);
4436
4437 /* For DFS paths, skip the first '\' of the UNC */
4438 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4439
Paulo Alcantara1c780222018-11-14 16:24:03 -02004440 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4441 ref_path, &referral, NULL);
4442 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004443 char *fake_devname = NULL;
4444
4445 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004446 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004447 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004448 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004449
Sean Finneydd613942011-04-11 13:19:30 +00004450 if (IS_ERR(mdata)) {
4451 rc = PTR_ERR(mdata);
4452 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004453 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004454 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004455 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004456 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004457 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004458 kfree(fake_devname);
4459 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004460 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004461 }
4462 kfree(full_path);
4463 return rc;
4464}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004465
4466static inline int get_next_dfs_tgt(const char *path,
4467 struct dfs_cache_tgt_list *tgt_list,
4468 struct dfs_cache_tgt_iterator **tgt_it)
4469{
4470 if (!*tgt_it)
4471 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4472 else
4473 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4474 return !*tgt_it ? -EHOSTDOWN : 0;
4475}
4476
4477static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4478 struct smb_vol *fake_vol, struct smb_vol *vol)
4479{
4480 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4481 int len = strlen(tgt) + 2;
4482 char *new_unc;
4483
4484 new_unc = kmalloc(len, GFP_KERNEL);
4485 if (!new_unc)
4486 return -ENOMEM;
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +10004487 scnprintf(new_unc, len, "\\%s", tgt);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004488
4489 kfree(vol->UNC);
4490 vol->UNC = new_unc;
4491
4492 if (fake_vol->prepath) {
4493 kfree(vol->prepath);
4494 vol->prepath = fake_vol->prepath;
4495 fake_vol->prepath = NULL;
4496 }
4497 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4498
4499 return 0;
4500}
4501
4502static int setup_dfs_tgt_conn(const char *path,
4503 const struct dfs_cache_tgt_iterator *tgt_it,
4504 struct cifs_sb_info *cifs_sb,
4505 struct smb_vol *vol,
4506 unsigned int *xid,
4507 struct TCP_Server_Info **server,
4508 struct cifs_ses **ses,
4509 struct cifs_tcon **tcon)
4510{
4511 int rc;
4512 struct dfs_info3_param ref = {0};
4513 char *mdata = NULL, *fake_devname = NULL;
Steve Frenchd0959b02019-10-05 10:53:58 -05004514 struct smb_vol fake_vol = {NULL};
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004515
4516 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4517
4518 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4519 if (rc)
4520 return rc;
4521
4522 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4523 &fake_devname);
4524 free_dfs_info_param(&ref);
4525
4526 if (IS_ERR(mdata)) {
4527 rc = PTR_ERR(mdata);
4528 mdata = NULL;
4529 } else {
4530 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4531 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4532 false);
4533 }
4534 kfree(mdata);
4535 kfree(fake_devname);
4536
4537 if (!rc) {
4538 /*
4539 * We use a 'fake_vol' here because we need pass it down to the
4540 * mount_{get,put} functions to test connection against new DFS
4541 * targets.
4542 */
4543 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4544 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4545 tcon);
4546 if (!rc) {
4547 /*
4548 * We were able to connect to new target server.
4549 * Update current volume info with new target server.
4550 */
4551 rc = update_vol_info(tgt_it, &fake_vol, vol);
4552 }
4553 }
4554 cifs_cleanup_volume_info_contents(&fake_vol);
4555 return rc;
4556}
4557
4558static int mount_do_dfs_failover(const char *path,
4559 struct cifs_sb_info *cifs_sb,
4560 struct smb_vol *vol,
4561 struct cifs_ses *root_ses,
4562 unsigned int *xid,
4563 struct TCP_Server_Info **server,
4564 struct cifs_ses **ses,
4565 struct cifs_tcon **tcon)
4566{
4567 int rc;
4568 struct dfs_cache_tgt_list tgt_list;
4569 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4570
4571 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4572 return -EOPNOTSUPP;
4573
4574 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4575 if (rc)
4576 return rc;
4577
4578 for (;;) {
4579 /* Get next DFS target server - if any */
4580 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4581 if (rc)
4582 break;
4583 /* Connect to next DFS target */
4584 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4585 ses, tcon);
4586 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4587 break;
4588 }
4589 if (!rc) {
4590 /*
4591 * Update DFS target hint in DFS referral cache with the target
4592 * server we successfully reconnected to.
4593 */
4594 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4595 cifs_sb->local_nls,
4596 cifs_remap(cifs_sb), path,
4597 tgt_it);
4598 }
4599 dfs_cache_free_tgts(&tgt_list);
4600 return rc;
4601}
Steve French2d6d5892009-04-09 00:36:44 +00004602#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004603
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004604int
Jeff Layton04db79b2011-07-06 08:10:38 -04004605cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004606 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004607{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004608 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004609
Steve Frenchc7c137b2018-06-06 17:59:29 -05004610 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004611 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004612
Jeff Layton7586b762008-12-01 18:41:49 -05004613 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004614 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004615 kfree(volume_info->username);
4616 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004617 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004619 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004620 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004621 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004622 /* In userspace mount helper we can get user name from alternate
4623 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004624 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625 }
4626
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004628 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004629 /* load_nls_default cannot return null */
4630 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004631 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004632 volume_info->local_nls = load_nls(volume_info->iocharset);
4633 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004634 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004635 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004636 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637 }
4638 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004639
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004640 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004641}
4642
4643struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004644cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004645{
4646 int rc;
4647 struct smb_vol *volume_info;
4648
Jeff Layton6ee95422012-11-26 11:09:57 -05004649 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004650 if (!volume_info)
4651 return ERR_PTR(-ENOMEM);
4652
Steve Frenchc7c137b2018-06-06 17:59:29 -05004653 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004654 if (rc) {
4655 cifs_cleanup_volume_info(volume_info);
4656 volume_info = ERR_PTR(rc);
4657 }
4658
4659 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004660}
4661
Aurelien Aptela6b50582016-05-25 19:59:09 +02004662static int
4663cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4664 unsigned int xid,
4665 struct cifs_tcon *tcon,
4666 struct cifs_sb_info *cifs_sb,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004667 char *full_path,
4668 int added_treename)
Aurelien Aptela6b50582016-05-25 19:59:09 +02004669{
4670 int rc;
4671 char *s;
4672 char sep, tmp;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004673 int skip = added_treename ? 1 : 0;
Aurelien Aptela6b50582016-05-25 19:59:09 +02004674
4675 sep = CIFS_DIR_SEP(cifs_sb);
4676 s = full_path;
4677
4678 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4679 while (rc == 0) {
4680 /* skip separators */
4681 while (*s == sep)
4682 s++;
4683 if (!*s)
4684 break;
4685 /* next separator */
4686 while (*s && *s != sep)
4687 s++;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004688 /*
4689 * if the treename is added, we then have to skip the first
4690 * part within the separators
4691 */
4692 if (skip) {
4693 skip = 0;
4694 continue;
4695 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004696 /*
4697 * temporarily null-terminate the path at the end of
4698 * the current component
4699 */
4700 tmp = *s;
4701 *s = 0;
4702 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4703 full_path);
4704 *s = tmp;
4705 }
4706 return rc;
4707}
4708
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004709/*
4710 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4711 * otherwise 0.
4712 */
4713static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4714 const unsigned int xid,
4715 struct TCP_Server_Info *server,
4716 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004717{
Jeff Layton1daaae82012-03-21 06:30:40 -04004718 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004719 char *full_path;
4720
4721 if (!server->ops->is_path_accessible)
4722 return -EOPNOTSUPP;
4723
4724 /*
4725 * cifs_build_path_to_root works only when we have a valid tcon
4726 */
4727 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4728 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4729 if (full_path == NULL)
4730 return -ENOMEM;
4731
4732 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4733
4734 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4735 full_path);
4736 if (rc != 0 && rc != -EREMOTE) {
4737 kfree(full_path);
4738 return rc;
4739 }
4740
4741 if (rc != -EREMOTE) {
4742 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004743 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004744 if (rc != 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004745 cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004746 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4747 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4748 rc = 0;
4749 }
4750 }
4751
4752 kfree(full_path);
4753 return rc;
4754}
4755
4756#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004757static inline void set_root_tcon(struct cifs_sb_info *cifs_sb,
4758 struct cifs_tcon *tcon,
4759 struct cifs_tcon **root)
4760{
4761 spin_lock(&cifs_tcp_ses_lock);
4762 tcon->tc_count++;
4763 tcon->remap = cifs_remap(cifs_sb);
4764 spin_unlock(&cifs_tcp_ses_lock);
4765 *root = tcon;
4766}
4767
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004768int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4769{
4770 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004771 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004772 struct cifs_ses *ses;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004773 struct cifs_tcon *root_tcon = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004774 struct cifs_tcon *tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004775 struct TCP_Server_Info *server;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004776 char *root_path = NULL, *full_path = NULL;
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004777 char *old_mountdata, *origin_mountdata = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004778 int count;
Al Virodd854462011-06-17 08:24:42 -04004779
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004780 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4781 if (!rc && tcon) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004782 /* If not a standalone DFS root, then check if path is remote */
4783 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4784 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4785 NULL);
4786 if (rc) {
4787 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4788 if (!rc)
4789 goto out;
4790 if (rc != -EREMOTE)
4791 goto error;
4792 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004793 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004794 /*
4795 * If first DFS target server went offline and we failed to connect it,
4796 * server and ses pointers are NULL at this point, though we still have
4797 * chance to get a cached DFS referral in expand_dfs_referral() and
4798 * retry next target available in it.
4799 *
4800 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4801 * performed against DFS path and *no* requests will be sent to server
4802 * for any new DFS referrals. Hence it's safe to skip checking whether
4803 * server or ses ptr is NULL.
4804 */
4805 if (rc == -EACCES || rc == -EOPNOTSUPP)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004806 goto error;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004807
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004808 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4809 if (IS_ERR(root_path)) {
4810 rc = PTR_ERR(root_path);
4811 root_path = NULL;
4812 goto error;
4813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004815 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4816 if (IS_ERR(full_path)) {
4817 rc = PTR_ERR(full_path);
4818 full_path = NULL;
4819 goto error;
4820 }
Sean Finneyc1508ca2011-04-11 13:19:31 +00004821 /*
4822 * Perform an unconditional check for whether there are DFS
4823 * referrals for this path without prefix, to provide support
4824 * for DFS referrals from w2k8 servers which don't seem to respond
4825 * with PATH_NOT_COVERED to requests that include the prefix.
4826 * Chase the referral if found, otherwise continue normally.
4827 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004828 old_mountdata = cifs_sb->mountdata;
4829 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004830
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004831 if (cifs_sb->mountdata == NULL) {
4832 rc = -ENOENT;
4833 goto error;
4834 }
4835
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004836 /* Save DFS root volume information for DFS refresh worker */
4837 origin_mountdata = kstrndup(cifs_sb->mountdata,
4838 strlen(cifs_sb->mountdata), GFP_KERNEL);
4839 if (!origin_mountdata) {
4840 rc = -ENOMEM;
4841 goto error;
4842 }
4843
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004844 if (cifs_sb->mountdata != old_mountdata) {
4845 /* If we were redirected, reconnect to new target server */
4846 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4847 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4848 }
4849 if (rc) {
4850 if (rc == -EACCES || rc == -EOPNOTSUPP)
4851 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004852 /* Perform DFS failover to any other DFS targets */
4853 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4854 &xid, &server, &ses, &tcon);
4855 if (rc)
4856 goto error;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004857 }
4858
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004859 kfree(root_path);
4860 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4861 if (IS_ERR(root_path)) {
4862 rc = PTR_ERR(root_path);
4863 root_path = NULL;
4864 goto error;
4865 }
4866 /* Cache out resolved root server */
4867 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4868 root_path + 1, NULL, NULL);
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004869 kfree(root_path);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004870 root_path = NULL;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004871
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004872 set_root_tcon(cifs_sb, tcon, &root_tcon);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004873
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004874 for (count = 1; ;) {
4875 if (!rc && tcon) {
4876 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4877 if (!rc || rc != -EREMOTE)
4878 break;
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004879 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004880 /*
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004881 * BB: when we implement proper loop detection,
4882 * we will remove this check. But now we need it
4883 * to prevent an indefinite loop if 'DFS tree' is
4884 * misconfigured (i.e. has loops).
Steve French6d3ea7e2012-11-28 22:34:41 -06004885 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004886 if (count++ > MAX_NESTED_LINKS) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004887 rc = -ELOOP;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004888 break;
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004889 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004890
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004891 kfree(full_path);
4892 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4893 if (IS_ERR(full_path)) {
4894 rc = PTR_ERR(full_path);
4895 full_path = NULL;
4896 break;
4897 }
4898
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004899 old_mountdata = cifs_sb->mountdata;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004900 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004901 true);
4902 if (rc)
4903 break;
Jeff Layton7b91e262009-07-23 15:22:30 -04004904
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004905 if (cifs_sb->mountdata != old_mountdata) {
4906 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4907 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4908 &tcon);
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004909 /*
4910 * Ensure that DFS referrals go through new root server.
4911 */
4912 if (!rc && tcon &&
4913 (tcon->share_flags & (SHI1005_FLAGS_DFS |
4914 SHI1005_FLAGS_DFS_ROOT))) {
4915 cifs_put_tcon(root_tcon);
4916 set_root_tcon(cifs_sb, tcon, &root_tcon);
4917 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004918 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004919 if (rc) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004920 if (rc == -EACCES || rc == -EOPNOTSUPP)
4921 break;
4922 /* Perform DFS failover to any other DFS targets */
4923 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4924 root_tcon->ses, &xid,
4925 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004926 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4927 !ses)
4928 goto error;
4929 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004930 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004931 cifs_put_tcon(root_tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004932
Jeff Layton9d002df2010-10-06 19:51:11 -04004933 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004934 goto error;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004935
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004936 spin_lock(&cifs_tcp_ses_lock);
4937 if (!tcon->dfs_path) {
4938 /* Save full path in new tcon to do failover when reconnecting tcons */
4939 tcon->dfs_path = full_path;
4940 full_path = NULL;
4941 tcon->remap = cifs_remap(cifs_sb);
4942 }
4943 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
YueHaibing2f0a6172018-12-18 01:34:39 +00004944 strlen(tcon->dfs_path),
4945 GFP_ATOMIC);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004946 if (!cifs_sb->origin_fullpath) {
4947 spin_unlock(&cifs_tcp_ses_lock);
4948 rc = -ENOMEM;
4949 goto error;
4950 }
4951 spin_unlock(&cifs_tcp_ses_lock);
4952
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004953 rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath);
Paulo Alcantarae511d312018-11-14 17:16:44 -02004954 if (rc) {
4955 kfree(cifs_sb->origin_fullpath);
4956 goto error;
4957 }
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004958 /*
4959 * After reconnecting to a different server, unique ids won't
4960 * match anymore, so we disable serverino. This prevents
4961 * dentry revalidation to think the dentry are stale (ESTALE).
4962 */
4963 cifs_autodisable_serverino(cifs_sb);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -03004964 /*
4965 * Force the use of prefix path to support failover on DFS paths that
4966 * resolve to targets that have different prefix paths.
4967 */
4968 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4969 kfree(cifs_sb->prepath);
4970 cifs_sb->prepath = vol->prepath;
4971 vol->prepath = NULL;
4972
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004973out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004974 free_xid(xid);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02004975 cifs_try_adding_channels(ses);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004976 return mount_setup_tlink(cifs_sb, ses, tcon);
4977
4978error:
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004979 kfree(full_path);
4980 kfree(root_path);
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004981 kfree(origin_mountdata);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004982 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983 return rc;
4984}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004985#else
4986int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4987{
4988 int rc = 0;
4989 unsigned int xid;
4990 struct cifs_ses *ses;
4991 struct cifs_tcon *tcon;
4992 struct TCP_Server_Info *server;
4993
4994 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4995 if (rc)
4996 goto error;
4997
4998 if (tcon) {
4999 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
5000 if (rc == -EREMOTE)
5001 rc = -EOPNOTSUPP;
5002 if (rc)
5003 goto error;
5004 }
5005
5006 free_xid(xid);
5007
5008 return mount_setup_tlink(cifs_sb, ses, tcon);
5009
5010error:
5011 mount_put_conns(cifs_sb, xid, server, ses, tcon);
5012 return rc;
5013}
5014#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005015
Jeff Layton8d1bca32011-06-11 21:17:10 -04005016/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01005017 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04005018 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04005020CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00005021 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022 const struct nls_table *nls_codepage)
5023{
5024 struct smb_hdr *smb_buffer;
5025 struct smb_hdr *smb_buffer_response;
5026 TCONX_REQ *pSMB;
5027 TCONX_RSP *pSMBr;
5028 unsigned char *bcc_ptr;
5029 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05005030 int length;
5031 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032
5033 if (ses == NULL)
5034 return -EIO;
5035
5036 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00005037 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00005039
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 smb_buffer_response = smb_buffer;
5041
5042 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
5043 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07005044
Pavel Shilovsky88257362012-05-23 14:01:59 +04005045 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005046 smb_buffer->Uid = ses->Suid;
5047 pSMB = (TCONX_REQ *) smb_buffer;
5048 pSMBr = (TCONX_RSP *) smb_buffer_response;
5049
5050 pSMB->AndXCommand = 0xFF;
5051 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01005053 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08005054 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00005055 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08005056 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00005057 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08005058 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005059 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08005060 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
5061 specified as required (when that support is added to
5062 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00005063 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08005064 by Samba (not sure whether other servers allow
5065 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00005066#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04005067 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05005068 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05005069 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00005070 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05005071 SECMODE_PW_ENCRYPT ? true : false,
5072 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00005073 else
5074#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06005075 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05005076 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05005077 if (rc) {
5078 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
5079 __func__, rc);
5080 cifs_buf_release(smb_buffer);
5081 return rc;
5082 }
Steve Frencheeac8042006-01-13 21:34:58 -08005083
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005084 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005085 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00005086 /* must align unicode strings */
5087 *bcc_ptr = 0; /* null byte password */
5088 bcc_ptr++;
5089 }
Steve Frencheeac8042006-01-13 21:34:58 -08005090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091
Jeff Layton38d77c52013-05-26 07:01:00 -04005092 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005093 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
5094
5095 if (ses->capabilities & CAP_STATUS32) {
5096 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
5097 }
5098 if (ses->capabilities & CAP_DFS) {
5099 smb_buffer->Flags2 |= SMBFLG2_DFS;
5100 }
5101 if (ses->capabilities & CAP_UNICODE) {
5102 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
5103 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06005104 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00005105 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00005106 (/* server len*/ + 256 /* share len */), nls_codepage);
5107 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005108 bcc_ptr += 2; /* skip trailing null */
5109 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005110 strcpy(bcc_ptr, tree);
5111 bcc_ptr += strlen(tree) + 1;
5112 }
5113 strcpy(bcc_ptr, "?????");
5114 bcc_ptr += strlen("?????");
5115 bcc_ptr += 1;
5116 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00005117 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
5118 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119 pSMB->ByteCount = cpu_to_le16(count);
5120
Steve French133672e2007-11-13 22:41:37 +00005121 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05005122 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123
Linus Torvalds1da177e2005-04-16 15:20:36 -07005124 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01005125 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00005126 bool is_unicode;
5127
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00005129 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130 tcon->tid = smb_buffer_response->Tid;
5131 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05005132 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005133 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00005134 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
5135 is_unicode = true;
5136 else
5137 is_unicode = false;
5138
Jeff Laytoncc20c032009-04-30 07:16:21 -04005139
Steve French50c2f752007-07-13 00:33:32 +00005140 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00005141 if (length == 3) {
5142 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
5143 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05005144 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01005145 tcon->ipc = true;
5146 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00005147 }
5148 } else if (length == 2) {
5149 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
5150 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05005151 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00005152 }
5153 }
Steve French50c2f752007-07-13 00:33:32 +00005154 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04005155 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05005156 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04005157
5158 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04005159 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06005160 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00005161 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04005162 nls_codepage);
5163
Joe Perchesf96637b2013-05-04 22:12:25 -05005164 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005165
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005166 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00005167 (smb_buffer_response->WordCount == 7))
5168 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00005169 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
5170 else
5171 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05005172 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173 }
5174
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00005175 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176 return rc;
5177}
5178
Al Viro2e32cf52013-10-03 12:53:37 -04005179static void delayed_free(struct rcu_head *p)
5180{
5181 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
5182 unload_nls(sbi->local_nls);
5183 kfree(sbi);
5184}
5185
Al Viro2a9b9952011-06-17 09:27:16 -04005186void
5187cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005188{
Jeff Laytonb647c352010-10-28 11:16:44 -04005189 struct rb_root *root = &cifs_sb->tlink_tree;
5190 struct rb_node *node;
5191 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192
Jeff Layton2de970f2010-10-06 19:51:12 -04005193 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
5194
Jeff Laytonb647c352010-10-28 11:16:44 -04005195 spin_lock(&cifs_sb->tlink_tree_lock);
5196 while ((node = rb_first(root))) {
5197 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5198 cifs_get_tlink(tlink);
5199 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5200 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00005201
Jeff Laytonb647c352010-10-28 11:16:44 -04005202 spin_unlock(&cifs_sb->tlink_tree_lock);
5203 cifs_put_tlink(tlink);
5204 spin_lock(&cifs_sb->tlink_tree_lock);
5205 }
5206 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005207
Al Virod757d712011-06-17 09:42:43 -04005208 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02005209 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005210#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02005211 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005212 kfree(cifs_sb->origin_fullpath);
5213#endif
Al Viro2e32cf52013-10-03 12:53:37 -04005214 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00005215}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005217int
5218cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005219{
5220 int rc = 0;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005221 struct TCP_Server_Info *server = cifs_ses_server(ses);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005222
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005223 if (!server->ops->need_neg || !server->ops->negotiate)
5224 return -ENOSYS;
5225
Jeff Layton198b5682010-04-24 07:57:48 -04005226 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005227 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04005228 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005229
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005230 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005231 if (rc == 0) {
5232 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04005233 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04005234 server->tcpStatus = CifsGood;
5235 else
5236 rc = -EHOSTDOWN;
5237 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238 }
Steve French26b994f2008-08-06 05:11:33 +00005239
Jeff Layton198b5682010-04-24 07:57:48 -04005240 return rc;
5241}
Steve French26b994f2008-08-06 05:11:33 +00005242
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005243int
5244cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
5245 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04005246{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005247 int rc = -ENOSYS;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005248 struct TCP_Server_Info *server = cifs_ses_server(ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005249
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02005250 if (!ses->binding) {
5251 ses->capabilities = server->capabilities;
5252 if (linuxExtEnabled == 0)
5253 ses->capabilities &= (~server->vals->cap_unix);
5254
5255 if (ses->auth_key.response) {
5256 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
5257 ses->auth_key.response);
5258 kfree(ses->auth_key.response);
5259 ses->auth_key.response = NULL;
5260 ses->auth_key.len = 0;
5261 }
5262 }
Steve French20418ac2009-04-30 16:13:32 +00005263
Joe Perchesf96637b2013-05-04 22:12:25 -05005264 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00005265 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04005266
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005267 if (server->ops->sess_setup)
5268 rc = server->ops->sess_setup(xid, ses, nls_info);
5269
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05005270 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10005271 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05005272
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273 return rc;
5274}
5275
Jeff Layton8a8798a2012-01-17 16:09:15 -05005276static int
5277cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
5278{
Jeff Layton3f618222013-06-12 19:52:14 -05005279 vol->sectype = ses->sectype;
5280
5281 /* krb5 is special, since we don't need username or pw */
5282 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05005283 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05005284
5285 return cifs_set_cifscreds(vol, ses);
5286}
5287
Steve French96daf2b2011-05-27 04:34:02 +00005288static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005289cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04005290{
Jeff Layton8a8798a2012-01-17 16:09:15 -05005291 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00005292 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
5293 struct cifs_ses *ses;
5294 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04005295 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04005296
5297 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03005298 if (vol_info == NULL)
5299 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04005300
Jeff Layton9d002df2010-10-06 19:51:11 -04005301 vol_info->local_nls = cifs_sb->local_nls;
5302 vol_info->linux_uid = fsuid;
5303 vol_info->cred_uid = fsuid;
5304 vol_info->UNC = master_tcon->treeName;
5305 vol_info->retry = master_tcon->retry;
5306 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05005307 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04005308 vol_info->local_lease = master_tcon->local_lease;
5309 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04005310 vol_info->sectype = master_tcon->ses->sectype;
5311 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04005312
Jeff Layton8a8798a2012-01-17 16:09:15 -05005313 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
5314 if (rc) {
5315 tcon = ERR_PTR(rc);
5316 goto out;
5317 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005318
5319 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305320 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005321 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305322 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005323
5324 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
5325 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00005326 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07005327 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04005328 goto out;
5329 }
5330
5331 tcon = cifs_get_tcon(ses, vol_info);
5332 if (IS_ERR(tcon)) {
5333 cifs_put_smb_ses(ses);
5334 goto out;
5335 }
5336
Steve Frenchce558b02018-05-31 19:16:54 -05005337 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
5338 if (tcon->posix_extensions)
5339 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05005340
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005341 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04005342 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05005343
Jeff Layton9d002df2010-10-06 19:51:11 -04005344out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05005345 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01005346 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005347 kfree(vol_info);
5348
5349 return tcon;
5350}
5351
Steve French96daf2b2011-05-27 04:34:02 +00005352struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005353cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5354{
5355 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5356}
5357
Jeff Laytonb647c352010-10-28 11:16:44 -04005358/* find and return a tlink with given uid */
5359static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005360tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005361{
5362 struct rb_node *node = root->rb_node;
5363 struct tcon_link *tlink;
5364
5365 while (node) {
5366 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5367
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005368 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005369 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005370 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005371 node = node->rb_right;
5372 else
5373 return tlink;
5374 }
5375 return NULL;
5376}
5377
5378/* insert a tcon_link into the tree */
5379static void
5380tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5381{
5382 struct rb_node **new = &(root->rb_node), *parent = NULL;
5383 struct tcon_link *tlink;
5384
5385 while (*new) {
5386 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5387 parent = *new;
5388
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005389 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005390 new = &((*new)->rb_left);
5391 else
5392 new = &((*new)->rb_right);
5393 }
5394
5395 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5396 rb_insert_color(&new_tlink->tl_rbnode, root);
5397}
5398
Jeff Layton9d002df2010-10-06 19:51:11 -04005399/*
5400 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5401 * current task.
5402 *
5403 * If the superblock doesn't refer to a multiuser mount, then just return
5404 * the master tcon for the mount.
5405 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305406 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005407 * exists, then check to see if it's pending construction. If it is then wait
5408 * for construction to complete. Once it's no longer pending, check to see if
5409 * it failed and either return an error or retry construction, depending on
5410 * the timeout.
5411 *
5412 * If one doesn't exist then insert a new tcon_link struct into the tree and
5413 * try to construct a new one.
5414 */
5415struct tcon_link *
5416cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5417{
5418 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005419 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005420 struct tcon_link *tlink, *newtlink;
5421
5422 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5423 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5424
5425 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005426 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005427 if (tlink)
5428 cifs_get_tlink(tlink);
5429 spin_unlock(&cifs_sb->tlink_tree_lock);
5430
5431 if (tlink == NULL) {
5432 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5433 if (newtlink == NULL)
5434 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005435 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005436 newtlink->tl_tcon = ERR_PTR(-EACCES);
5437 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5438 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5439 cifs_get_tlink(newtlink);
5440
Jeff Layton9d002df2010-10-06 19:51:11 -04005441 spin_lock(&cifs_sb->tlink_tree_lock);
5442 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005443 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005444 if (tlink) {
5445 cifs_get_tlink(tlink);
5446 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005447 kfree(newtlink);
5448 goto wait_for_construction;
5449 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005450 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005451 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5452 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005453 } else {
5454wait_for_construction:
5455 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005456 TASK_INTERRUPTIBLE);
5457 if (ret) {
5458 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005459 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005460 }
5461
5462 /* if it's good, return it */
5463 if (!IS_ERR(tlink->tl_tcon))
5464 return tlink;
5465
5466 /* return error if we tried this already recently */
5467 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5468 cifs_put_tlink(tlink);
5469 return ERR_PTR(-EACCES);
5470 }
5471
5472 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5473 goto wait_for_construction;
5474 }
5475
5476 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5477 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5478 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5479
5480 if (IS_ERR(tlink->tl_tcon)) {
5481 cifs_put_tlink(tlink);
5482 return ERR_PTR(-EACCES);
5483 }
5484
5485 return tlink;
5486}
Jeff Layton2de970f2010-10-06 19:51:12 -04005487
5488/*
5489 * periodic workqueue job that scans tcon_tree for a superblock and closes
5490 * out tcons.
5491 */
5492static void
5493cifs_prune_tlinks(struct work_struct *work)
5494{
5495 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5496 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005497 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005498 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005499 struct rb_node *tmp;
5500 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005501
Jeff Laytonb647c352010-10-28 11:16:44 -04005502 /*
5503 * Because we drop the spinlock in the loop in order to put the tlink
5504 * it's not guarded against removal of links from the tree. The only
5505 * places that remove entries from the tree are this function and
5506 * umounts. Because this function is non-reentrant and is canceled
5507 * before umount can proceed, this is safe.
5508 */
5509 spin_lock(&cifs_sb->tlink_tree_lock);
5510 node = rb_first(root);
5511 while (node != NULL) {
5512 tmp = node;
5513 node = rb_next(tmp);
5514 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5515
5516 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5517 atomic_read(&tlink->tl_count) != 0 ||
5518 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5519 continue;
5520
5521 cifs_get_tlink(tlink);
5522 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5523 rb_erase(tmp, root);
5524
Jeff Layton2de970f2010-10-06 19:51:12 -04005525 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005526 cifs_put_tlink(tlink);
5527 spin_lock(&cifs_sb->tlink_tree_lock);
5528 }
5529 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005530
Jeff Laytonda472fc2012-03-23 14:40:53 -04005531 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005532 TLINK_IDLE_EXPIRE);
5533}