blob: c2a92e26fef44243ce1aadda8ee45ba432681f5d [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
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100064#include "fs_context.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
Linus Torvalds1da177e2005-04-16 15:20:36 -070066extern mempool_t *cifs_req_poolp;
Steve Frenchf92a7202018-05-24 04:11:07 -050067extern bool disable_legacy_dialects;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
Jeff Layton2de970f2010-10-06 19:51:12 -040069/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040070#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040071#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040072
Rohith Surabattula8e670f72020-09-18 05:37:28 +000073/* Drop the connection to not overload the server */
74#define NUM_STATUS_IO_TIMEOUT 5
75
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040076enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040077 /* Mount options that take no arguments */
78 Opt_user_xattr, Opt_nouser_xattr,
79 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040080 Opt_forcegid, Opt_noforcegid,
Steve French3e7a02d2019-09-11 21:46:20 -050081 Opt_noblocksend, Opt_noautotune, Opt_nolease,
Steve French82e93672020-05-19 03:06:57 -050082 Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_nodelete,
Steve French2baa2682014-09-27 02:19:01 -050083 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040084 Opt_mapchars, Opt_nomapchars, Opt_sfu,
85 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
Steve Frenchb3266142018-05-20 23:41:10 -050086 Opt_noposixpaths, Opt_nounix, Opt_unix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040087 Opt_nocase,
88 Opt_brl, Opt_nobrl,
Steve French3d4ef9a2018-04-25 22:19:09 -050089 Opt_handlecache, Opt_nohandlecache,
Steve French95932652016-09-23 01:36:34 -050090 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040091 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
92 Opt_nohard, Opt_nosoft,
93 Opt_nointr, Opt_intr,
94 Opt_nostrictsync, Opt_strictsync,
95 Opt_serverino, Opt_noserverino,
96 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
97 Opt_acl, Opt_noacl, Opt_locallease,
Steve French4f5c10f2019-09-03 21:18:49 -050098 Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040099 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -0400100 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -0500101 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -0600102 Opt_resilient, Opt_noresilient,
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -0300103 Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200104 Opt_multichannel, Opt_nomultichannel,
Steve French9fe5ff12019-06-24 20:39:04 -0500105 Opt_compress,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400106
107 /* Mount options which take numeric value */
108 Opt_backupuid, Opt_backupgid, Opt_uid,
109 Opt_cruid, Opt_gid, Opt_file_mode,
110 Opt_dirmode, Opt_port,
Steve French563317e2019-09-08 23:22:02 -0500111 Opt_min_enc_offload,
Steve Frenche8506d22019-02-28 21:32:15 -0600112 Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
Steve Frenchca567eb2019-03-29 16:31:07 -0500113 Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200114 Opt_snapshot, Opt_max_channels,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400115
116 /* Mount options which take string value */
117 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400118 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400119 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400120 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400121
122 /* Mount options to be ignored */
123 Opt_ignore,
124
125 /* Options which could be blank */
126 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100127 Opt_blank_user,
128 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400129
130 Opt_err
131};
132
133static const match_table_t cifs_mount_option_tokens = {
134
135 { Opt_user_xattr, "user_xattr" },
136 { Opt_nouser_xattr, "nouser_xattr" },
137 { Opt_forceuid, "forceuid" },
138 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400139 { Opt_forcegid, "forcegid" },
140 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400141 { Opt_noblocksend, "noblocksend" },
142 { Opt_noautotune, "noautotune" },
Steve French3e7a02d2019-09-11 21:46:20 -0500143 { Opt_nolease, "nolease" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400144 { Opt_hard, "hard" },
145 { Opt_soft, "soft" },
146 { Opt_perm, "perm" },
147 { Opt_noperm, "noperm" },
Steve French82e93672020-05-19 03:06:57 -0500148 { Opt_nodelete, "nodelete" },
Steve French2baa2682014-09-27 02:19:01 -0500149 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400150 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500151 { Opt_mapposix, "mapposix" }, /* SFM style */
152 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400153 { Opt_sfu, "sfu" },
154 { Opt_nosfu, "nosfu" },
155 { Opt_nodfs, "nodfs" },
156 { Opt_posixpaths, "posixpaths" },
157 { Opt_noposixpaths, "noposixpaths" },
158 { Opt_nounix, "nounix" },
159 { Opt_nounix, "nolinux" },
Steve Frenchb3266142018-05-20 23:41:10 -0500160 { Opt_nounix, "noposix" },
161 { Opt_unix, "unix" },
162 { Opt_unix, "linux" },
163 { Opt_unix, "posix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400164 { Opt_nocase, "nocase" },
165 { Opt_nocase, "ignorecase" },
166 { Opt_brl, "brl" },
167 { Opt_nobrl, "nobrl" },
Steve French3d4ef9a2018-04-25 22:19:09 -0500168 { Opt_handlecache, "handlecache" },
169 { Opt_nohandlecache, "nohandlecache" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400170 { Opt_nobrl, "nolock" },
171 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400172 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400173 { Opt_setuids, "setuids" },
174 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500175 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400176 { Opt_dynperm, "dynperm" },
177 { Opt_nodynperm, "nodynperm" },
178 { Opt_nohard, "nohard" },
179 { Opt_nosoft, "nosoft" },
180 { Opt_nointr, "nointr" },
181 { Opt_intr, "intr" },
182 { Opt_nostrictsync, "nostrictsync" },
183 { Opt_strictsync, "strictsync" },
184 { Opt_serverino, "serverino" },
185 { Opt_noserverino, "noserverino" },
186 { Opt_rwpidforward, "rwpidforward" },
Steve French412094a2019-06-24 02:01:42 -0500187 { Opt_modesid, "modefromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400188 { Opt_cifsacl, "cifsacl" },
189 { Opt_nocifsacl, "nocifsacl" },
190 { Opt_acl, "acl" },
191 { Opt_noacl, "noacl" },
192 { Opt_locallease, "locallease" },
193 { Opt_sign, "sign" },
Steve French4f5c10f2019-09-03 21:18:49 -0500194 { Opt_ignore_signature, "signloosely" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400195 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400196 { Opt_noac, "noac" },
197 { Opt_fsc, "fsc" },
198 { Opt_mfsymlinks, "mfsymlinks" },
199 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400200 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400201 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500202 { Opt_persistent, "persistenthandles"},
203 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600204 { Opt_resilient, "resilienthandles"},
205 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530206 { Opt_domainauto, "domainauto"},
Long Li8339dd32017-11-07 01:54:55 -0700207 { Opt_rdma, "rdma"},
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200208 { Opt_multichannel, "multichannel" },
209 { Opt_nomultichannel, "nomultichannel" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400210
211 { Opt_backupuid, "backupuid=%s" },
212 { Opt_backupgid, "backupgid=%s" },
213 { Opt_uid, "uid=%s" },
214 { Opt_cruid, "cruid=%s" },
215 { Opt_gid, "gid=%s" },
216 { Opt_file_mode, "file_mode=%s" },
217 { Opt_dirmode, "dirmode=%s" },
218 { Opt_dirmode, "dir_mode=%s" },
219 { Opt_port, "port=%s" },
Steve French563317e2019-09-08 23:22:02 -0500220 { Opt_min_enc_offload, "esize=%s" },
Steve Frenche8506d22019-02-28 21:32:15 -0600221 { Opt_blocksize, "bsize=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400222 { Opt_rsize, "rsize=%s" },
223 { Opt_wsize, "wsize=%s" },
224 { Opt_actimeo, "actimeo=%s" },
Steve Frenchca567eb2019-03-29 16:31:07 -0500225 { Opt_handletimeout, "handletimeout=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600226 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500227 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600228 { Opt_snapshot, "snapshot=%s" },
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200229 { Opt_max_channels, "max_channels=%s" },
Steve French9fe5ff12019-06-24 20:39:04 -0500230 { Opt_compress, "compress=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400231
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100232 { Opt_blank_user, "user=" },
233 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400234 { Opt_user, "user=%s" },
235 { Opt_user, "username=%s" },
236 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100237 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400238 { Opt_pass, "pass=%s" },
239 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100240 { Opt_blank_ip, "ip=" },
241 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400242 { Opt_ip, "ip=%s" },
243 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400244 { Opt_ignore, "unc=%s" },
245 { Opt_ignore, "target=%s" },
246 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400247 { Opt_domain, "dom=%s" },
248 { Opt_domain, "domain=%s" },
249 { Opt_domain, "workgroup=%s" },
250 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400251 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400252 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400253 { Opt_netbiosname, "netbiosname=%s" },
254 { Opt_servern, "servern=%s" },
255 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400256 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400257 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400258 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400259
260 { Opt_ignore, "cred" },
261 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400262 { Opt_ignore, "cred=%s" },
263 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400264 { Opt_ignore, "guest" },
265 { Opt_ignore, "rw" },
266 { Opt_ignore, "ro" },
267 { Opt_ignore, "suid" },
268 { Opt_ignore, "nosuid" },
269 { Opt_ignore, "exec" },
270 { Opt_ignore, "noexec" },
271 { Opt_ignore, "nodev" },
272 { Opt_ignore, "noauto" },
273 { Opt_ignore, "dev" },
274 { Opt_ignore, "mand" },
275 { Opt_ignore, "nomand" },
Steve French9b9c5be2018-09-22 12:07:06 -0500276 { Opt_ignore, "relatime" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400277 { Opt_ignore, "_netdev" },
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -0300278 { Opt_rootfs, "rootfs" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400279
280 { Opt_err, NULL }
281};
282
Jeff Layton15b6a472012-05-16 07:50:15 -0400283/* cache flavors */
284enum {
285 Opt_cache_loose,
286 Opt_cache_strict,
287 Opt_cache_none,
Steve French83bbfa72019-08-27 23:58:54 -0500288 Opt_cache_ro,
Steve French41e033f2019-08-30 02:12:41 -0500289 Opt_cache_rw,
Jeff Layton15b6a472012-05-16 07:50:15 -0400290 Opt_cache_err
291};
292
293static const match_table_t cifs_cacheflavor_tokens = {
294 { Opt_cache_loose, "loose" },
295 { Opt_cache_strict, "strict" },
296 { Opt_cache_none, "none" },
Steve French83bbfa72019-08-27 23:58:54 -0500297 { Opt_cache_ro, "ro" },
Steve French41e033f2019-08-30 02:12:41 -0500298 { Opt_cache_rw, "singleclient" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400299 { Opt_cache_err, NULL }
300};
301
Jeff Layton23db65f2012-05-15 12:20:51 -0400302static const match_table_t cifs_smb_version_tokens = {
303 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600304 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000305 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500306 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500307 { Smb_302, SMB302_VERSION_STRING },
Kenneth D'souza4a3b38a2018-11-17 10:33:30 +0530308 { Smb_302, ALT_SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600309 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500310 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French9764c022017-09-17 10:41:35 -0500311 { Smb_3any, SMB3ANY_VERSION_STRING },
312 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600313 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400314};
315
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300316static int ip_connect(struct TCP_Server_Info *server);
317static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400318static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400319static void cifs_prune_tlinks(struct work_struct *work);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200320static char *extract_hostname(const char *unc);
321
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200322/*
323 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
324 * get their ip addresses changed at some point.
325 *
326 * This should be called with server->srv_mutex held.
327 */
328#ifdef CONFIG_CIFS_DFS_UPCALL
329static int reconn_set_ipaddr(struct TCP_Server_Info *server)
330{
331 int rc;
332 int len;
333 char *unc, *ipaddr = NULL;
334
335 if (!server->hostname)
336 return -EINVAL;
337
338 len = strlen(server->hostname) + 3;
339
340 unc = kmalloc(len, GFP_KERNEL);
341 if (!unc) {
342 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
343 return -ENOMEM;
344 }
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +1000345 scnprintf(unc, len, "\\\\%s", server->hostname);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200346
347 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
348 kfree(unc);
349
350 if (rc < 0) {
351 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
352 __func__, server->hostname, rc);
353 return rc;
354 }
355
Ronnie Sahlbergfada37f2020-04-21 12:37:39 +1000356 spin_lock(&cifs_tcp_ses_lock);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200357 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
358 strlen(ipaddr));
Ronnie Sahlbergfada37f2020-04-21 12:37:39 +1000359 spin_unlock(&cifs_tcp_ses_lock);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200360 kfree(ipaddr);
361
362 return !rc ? -1 : 0;
363}
364#else
365static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
366{
367 return 0;
368}
369#endif
370
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200371#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200372/* These functions must be called with server->srv_mutex held */
Paulo Alcantara7d397a02020-07-21 09:36:40 -0300373static void reconn_set_next_dfs_target(struct TCP_Server_Info *server,
374 struct cifs_sb_info *cifs_sb,
375 struct dfs_cache_tgt_list *tgt_list,
376 struct dfs_cache_tgt_iterator **tgt_it)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200377{
378 const char *name;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200379
Paulo Alcantara7d397a02020-07-21 09:36:40 -0300380 if (!cifs_sb || !cifs_sb->origin_fullpath)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200381 return;
382
383 if (!*tgt_it) {
384 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
385 } else {
386 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
387 if (!*tgt_it)
388 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
389 }
390
391 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
392
393 name = dfs_cache_get_tgt_name(*tgt_it);
394
395 kfree(server->hostname);
396
397 server->hostname = extract_hostname(name);
Dan Carpenter84288172019-01-05 15:25:29 +0300398 if (IS_ERR(server->hostname)) {
399 cifs_dbg(FYI,
400 "%s: failed to extract hostname from target: %ld\n",
401 __func__, PTR_ERR(server->hostname));
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200402 }
403}
404
405static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
Paulo Alcantarabaf3f082020-05-19 15:38:29 -0300406 struct dfs_cache_tgt_list *tl)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200407{
408 if (!cifs_sb->origin_fullpath)
409 return -EOPNOTSUPP;
410 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
411}
412#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Jeff Laytond5c56052008-12-01 18:42:33 -0500414/*
415 * cifs tcp session reconnection
416 *
417 * mark tcp session as reconnecting so temporarily locked
418 * mark all smb sessions as reconnecting for tcp session
419 * reconnect tcp session
420 * wake up waiters on reconnection? - (not needed currently)
421 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400422int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423cifs_reconnect(struct TCP_Server_Info *server)
424{
425 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500426 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000427 struct cifs_ses *ses;
428 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000429 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400430 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200431#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300432 struct super_block *sb = NULL;
Paulo Alcantara23324402018-11-20 14:37:18 -0200433 struct cifs_sb_info *cifs_sb = NULL;
434 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200435 struct dfs_cache_tgt_iterator *tgt_it = NULL;
436#endif
Steve French50c2f752007-07-13 00:33:32 +0000437
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200439 server->nr_targets = 1;
440#ifdef CONFIG_CIFS_DFS_UPCALL
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000441 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -0300442 sb = cifs_get_tcp_super(server);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300443 if (IS_ERR(sb)) {
444 rc = PTR_ERR(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200445 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
446 __func__, rc);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300447 sb = NULL;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200448 } else {
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300449 cifs_sb = CIFS_SB(sb);
Paulo Alcantarabaf3f082020-05-19 15:38:29 -0300450 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list);
Paulo Alcantaraa5293032020-07-21 09:36:41 -0300451 if (rc) {
452 cifs_sb = NULL;
453 if (rc != -EOPNOTSUPP) {
454 cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
455 __func__);
456 }
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200457 } else {
458 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
459 }
460 }
461 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
462 server->nr_targets);
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000463 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200464#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000465 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000466 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 next time through the loop */
468 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300469#ifdef CONFIG_CIFS_DFS_UPCALL
470 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -0300471 cifs_put_tcp_super(sb);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300472#endif
Stefan Metzmachere2e87512020-02-24 14:31:02 -0600473 wake_up(&server->response_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 return rc;
475 } else
476 server->tcpStatus = CifsNeedReconnect;
477 spin_unlock(&GlobalMid_Lock);
478 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400479 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
Steve French6e4d3bb2018-09-22 11:25:04 -0500481 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500482 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 /* before reconnecting the tcp session, mark the smb session (uid)
485 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500486 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
487 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530488 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500489 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000490 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500491 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500492 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000493 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500494 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100496 if (ses->tcon_ipc)
497 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530499 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500500
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500502 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500503 mutex_lock(&server->srv_mutex);
Long Li1d2a4f52019-05-13 21:01:28 -0700504 if (server->ssocket) {
505 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
506 server->ssocket->state, server->ssocket->flags);
507 kernel_sock_shutdown(server->ssocket, SHUT_WR);
508 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
509 server->ssocket->state, server->ssocket->flags);
510 sock_release(server->ssocket);
511 server->ssocket = NULL;
512 }
513 server->sequence_number = 0;
514 server->session_estab = false;
515 kfree(server->session_key.response);
516 server->session_key.response = NULL;
517 server->session_key.len = 0;
518 server->lstrp = jiffies;
Long Li214bab42019-04-05 21:36:35 +0000519
520 /* mark submitted MIDs for retry and issue callback */
521 INIT_LIST_HEAD(&retry_list);
522 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
523 spin_lock(&GlobalMid_Lock);
524 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
525 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700526 kref_get(&mid_entry->refcount);
Long Li214bab42019-04-05 21:36:35 +0000527 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
528 mid_entry->mid_state = MID_RETRY_NEEDED;
529 list_move(&mid_entry->qhead, &retry_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700530 mid_entry->mid_flags |= MID_DELETED;
Long Li214bab42019-04-05 21:36:35 +0000531 }
532 spin_unlock(&GlobalMid_Lock);
Long Li1d2a4f52019-05-13 21:01:28 -0700533 mutex_unlock(&server->srv_mutex);
Long Li214bab42019-04-05 21:36:35 +0000534
535 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
536 list_for_each_safe(tmp, tmp2, &retry_list) {
537 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
538 list_del_init(&mid_entry->qhead);
539 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700540 cifs_mid_q_entry_release(mid_entry);
Long Li214bab42019-04-05 21:36:35 +0000541 }
542
Long Li1d2a4f52019-05-13 21:01:28 -0700543 if (cifs_rdma_enabled(server)) {
544 mutex_lock(&server->srv_mutex);
Long Li050b8c32019-04-04 11:35:42 -0500545 smbd_destroy(server);
Long Li1d2a4f52019-05-13 21:01:28 -0700546 mutex_unlock(&server->srv_mutex);
547 }
Jeff Layton3c1105d2011-05-22 07:09:13 -0400548
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400549 do {
Steve French6c3d8902006-07-31 22:46:20 +0000550 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300551
Jeff Layton73e216a2013-09-05 08:38:10 -0400552 mutex_lock(&server->srv_mutex);
Paulo Alcantaraaaa3aef2020-05-19 15:38:27 -0300553#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200554 /*
555 * Set up next DFS target server (if any) for reconnect. If DFS
556 * feature is disabled, then we will retry last server we
557 * connected to before.
558 */
Paulo Alcantara7d397a02020-07-21 09:36:40 -0300559 reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it);
Paulo Alcantaraaaa3aef2020-05-19 15:38:27 -0300560#endif
561 rc = reconn_set_ipaddr(server);
562 if (rc) {
563 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
564 __func__, rc);
565 }
566
Long Li781a8052017-11-22 17:38:36 -0700567 if (cifs_rdma_enabled(server))
568 rc = smbd_reconnect(server);
569 else
570 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000571 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500572 cifs_dbg(FYI, "reconnect error %d\n", rc);
Federico Sauter4afe2602015-03-17 17:45:28 +0100573 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700574 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 } else {
576 atomic_inc(&tcpSesReconnectCount);
Pavel Shilovsky335b7b62019-01-16 11:12:41 -0800577 set_credits(server, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000579 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000580 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000581 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100582 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400584 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500585
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200586#ifdef CONFIG_CIFS_DFS_UPCALL
587 if (tgt_it) {
588 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
589 tgt_it);
590 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000591 cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200592 __func__, rc);
593 }
594 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
595 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000596 cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200597 __func__, rc);
598 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200599 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300600
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200601 }
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300602
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -0300603 cifs_put_tcp_super(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200604#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400605 if (server->tcpStatus == CifsNeedNegotiate)
606 mod_delayed_work(cifsiod_wq, &server->echo, 0);
607
Stefan Metzmachere2e87512020-02-24 14:31:02 -0600608 wake_up(&server->response_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 return rc;
610}
611
Jeff Laytonc74093b2011-01-11 07:24:23 -0500612static void
613cifs_echo_request(struct work_struct *work)
614{
615 int rc;
616 struct TCP_Server_Info *server = container_of(work,
617 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400618 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500619
Jeff Layton247ec9b2011-02-04 17:09:50 -0500620 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400621 * If we need to renegotiate, set echo interval to zero to
622 * immediately call echo service where we can renegotiate.
623 */
624 if (server->tcpStatus == CifsNeedNegotiate)
625 echo_interval = 0;
626 else
627 echo_interval = server->echo_interval;
628
629 /*
630 * We cannot send an echo if it is disabled.
631 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500632 */
Steve French4fcd1812016-06-22 20:12:05 -0500633
634 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400635 server->tcpStatus == CifsExiting ||
636 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400637 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600638 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500639 goto requeue_echo;
640
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400641 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500642 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500643 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
644 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500645
646requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400647 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500648}
649
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400650static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400651allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400652{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400653 if (!server->bigbuf) {
654 server->bigbuf = (char *)cifs_buf_get();
655 if (!server->bigbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000656 cifs_server_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400657 msleep(3000);
658 /* retry will check if exiting */
659 return false;
660 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400661 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400662 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400663 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400664 }
665
Jeff Layton2a37ef92011-10-19 15:29:23 -0400666 if (!server->smallbuf) {
667 server->smallbuf = (char *)cifs_small_buf_get();
668 if (!server->smallbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000669 cifs_server_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400670 msleep(1000);
671 /* retry will check if exiting */
672 return false;
673 }
674 /* beginning of smb buffer is cleared in our buf_get */
675 } else {
676 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400677 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400678 }
679
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400680 return true;
681}
682
Jeff Laytonba749e62011-10-11 06:41:32 -0400683static bool
684server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400685{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300686 /*
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000687 * We need to wait 3 echo intervals to make sure we handle such
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300688 * situations right:
689 * 1s client sends a normal SMB request
Ronnie Sahlbergbecc2ba2019-07-24 11:43:49 +1000690 * 2s client gets a response
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300691 * 30s echo workqueue job pops, and decides we got a response recently
692 * and don't need to send another
693 * ...
694 * 65s kernel_recvmsg times out, and we see that we haven't gotten
695 * a response in >60s.
696 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200697 if ((server->tcpStatus == CifsGood ||
698 server->tcpStatus == CifsNeedNegotiate) &&
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000699 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000700 cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
701 (3 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400702 cifs_reconnect(server);
Jeff Laytonba749e62011-10-11 06:41:32 -0400703 return true;
704 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400705
Jeff Laytonba749e62011-10-11 06:41:32 -0400706 return false;
707}
708
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800709static inline bool
710zero_credits(struct TCP_Server_Info *server)
711{
712 int val;
713
714 spin_lock(&server->req_lock);
715 val = server->credits + server->echo_credits + server->oplock_credits;
716 if (server->in_flight == 0 && val == 0) {
717 spin_unlock(&server->req_lock);
718 return true;
719 }
720 spin_unlock(&server->req_lock);
721 return false;
722}
723
Al Viro71335662016-01-09 19:54:50 -0500724static int
725cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400726{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400727 int length = 0;
728 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400729
Al Viro71335662016-01-09 19:54:50 -0500730 smb_msg->msg_control = NULL;
731 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400732
Al Viro71335662016-01-09 19:54:50 -0500733 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500734 try_to_freeze();
735
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800736 /* reconnect if no credits and no requests in flight */
737 if (zero_credits(server)) {
738 cifs_reconnect(server);
739 return -ECONNABORTED;
740 }
741
Al Viro71335662016-01-09 19:54:50 -0500742 if (server_unresponsive(server))
743 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700744 if (cifs_rdma_enabled(server) && server->smbd_conn)
745 length = smbd_recv(server->smbd_conn, smb_msg);
746 else
747 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500748
749 if (server->tcpStatus == CifsExiting)
750 return -ESHUTDOWN;
751
752 if (server->tcpStatus == CifsNeedReconnect) {
753 cifs_reconnect(server);
754 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400755 }
756
Al Viro71335662016-01-09 19:54:50 -0500757 if (length == -ERESTARTSYS ||
758 length == -EAGAIN ||
759 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400760 /*
761 * Minimum sleep to prevent looping, allowing socket
762 * to clear and app threads to set tcpStatus
763 * CifsNeedReconnect if server hung.
764 */
765 usleep_range(1000, 2000);
766 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400767 continue;
Al Viro71335662016-01-09 19:54:50 -0500768 }
769
770 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500771 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400772 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500773 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400774 }
775 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400776 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400777}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400778
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400779int
780cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
781 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400782{
Al Viro71335662016-01-09 19:54:50 -0500783 struct msghdr smb_msg;
784 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100785 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400786
Al Viro71335662016-01-09 19:54:50 -0500787 return cifs_readv_from_socket(server, &smb_msg);
788}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400789
Al Viro71335662016-01-09 19:54:50 -0500790int
791cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700792 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500793{
794 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700795 struct bio_vec bv = {
796 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100797 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500798 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400799}
800
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400801static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400802is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400803{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400804 /*
805 * The first byte big endian of the length field,
806 * is actually not part of the length but the type
807 * with the most common, zero, as regular data.
808 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400809 switch (type) {
810 case RFC1002_SESSION_MESSAGE:
811 /* Regular SMB response */
812 return true;
813 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500814 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400815 break;
816 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500817 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400818 break;
819 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400820 /*
821 * We get this from Windows 98 instead of an error on
822 * SMB negprot response.
823 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500824 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400825 /* give server a second to clean up */
826 msleep(1000);
827 /*
828 * Always try 445 first on reconnect since we get NACK
829 * on some if we ever connected to port 139 (the NACK
830 * is since we do not begin with RFC1001 session
831 * initialize frame).
832 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400833 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400834 cifs_reconnect(server);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400835 break;
836 default:
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000837 cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400838 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400839 }
840
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400841 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400842}
843
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400844void
845dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400846{
847#ifdef CONFIG_CIFS_STATS2
848 mid->when_received = jiffies;
849#endif
850 spin_lock(&GlobalMid_Lock);
851 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400852 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400853 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400854 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000855 /*
856 * Trying to handle/dequeue a mid after the send_recv()
857 * function has finished processing it is a bug.
858 */
859 if (mid->mid_flags & MID_DELETED)
Joe Perchesa0a30362020-04-14 22:42:53 -0700860 pr_warn_once("trying to dequeue a deleted mid\n");
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700861 else {
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000862 list_del_init(&mid->qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700863 mid->mid_flags |= MID_DELETED;
864 }
Jeff Laytonea1f4502011-10-19 15:29:05 -0400865 spin_unlock(&GlobalMid_Lock);
866}
867
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800868static unsigned int
869smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
870{
871 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
872
873 /*
874 * SMB1 does not use credits.
875 */
876 if (server->vals->header_preamble_size)
877 return 0;
878
879 return le16_to_cpu(shdr->CreditRequest);
880}
881
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400882static void
883handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400884 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400885{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400886 if (server->ops->check_trans2 &&
887 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400888 return;
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800889 mid->credits_received = smb2_get_credits_from_hdr(buf, server);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400890 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400891 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400892 /* Was previous buf put in mpx struct for multi-rsp? */
893 if (!mid->multiRsp) {
894 /* smb buffer will be freed by user thread */
895 if (server->large_buf)
896 server->bigbuf = NULL;
897 else
898 server->smallbuf = NULL;
899 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400900 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400901}
902
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400903static void clean_demultiplex_info(struct TCP_Server_Info *server)
904{
905 int length;
906
907 /* take it off the list, if it's not already */
908 spin_lock(&cifs_tcp_ses_lock);
909 list_del_init(&server->tcp_ses_list);
910 spin_unlock(&cifs_tcp_ses_lock);
911
912 spin_lock(&GlobalMid_Lock);
913 server->tcpStatus = CifsExiting;
914 spin_unlock(&GlobalMid_Lock);
915 wake_up_all(&server->response_q);
916
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400917 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300918 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400919 if (server->credits <= 0)
920 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300921 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400922 /*
923 * Although there should not be any requests blocked on this queue it
924 * can not hurt to be paranoid and try to wake up requests that may
925 * haven been blocked when more than 50 at time were on the wire to the
926 * same server - they now will see the session is in exit state and get
927 * out of SendReceive.
928 */
929 wake_up_all(&server->request_q);
930 /* give those requests time to exit */
931 msleep(125);
Long Li050b8c32019-04-04 11:35:42 -0500932 if (cifs_rdma_enabled(server))
933 smbd_destroy(server);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400934 if (server->ssocket) {
935 sock_release(server->ssocket);
936 server->ssocket = NULL;
937 }
938
939 if (!list_empty(&server->pending_mid_q)) {
940 struct list_head dispose_list;
941 struct mid_q_entry *mid_entry;
942 struct list_head *tmp, *tmp2;
943
944 INIT_LIST_HEAD(&dispose_list);
945 spin_lock(&GlobalMid_Lock);
946 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
947 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500948 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700949 kref_get(&mid_entry->refcount);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400950 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400951 list_move(&mid_entry->qhead, &dispose_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700952 mid_entry->mid_flags |= MID_DELETED;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400953 }
954 spin_unlock(&GlobalMid_Lock);
955
956 /* now walk dispose list and issue callbacks */
957 list_for_each_safe(tmp, tmp2, &dispose_list) {
958 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500959 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400960 list_del_init(&mid_entry->qhead);
961 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700962 cifs_mid_q_entry_release(mid_entry);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400963 }
964 /* 1/8th of sec is more than enough time for them to exit */
965 msleep(125);
966 }
967
968 if (!list_empty(&server->pending_mid_q)) {
969 /*
970 * mpx threads have not exited yet give them at least the smb
971 * send timeout time for long ops.
972 *
973 * Due to delays on oplock break requests, we need to wait at
974 * least 45 seconds before giving up on a request getting a
975 * response and going ahead and killing cifsd.
976 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500977 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400978 msleep(46000);
979 /*
980 * If threads still have not exited they are probably never
981 * coming home not much else we can do but free the memory.
982 */
983 }
984
985 kfree(server->hostname);
986 kfree(server);
987
988 length = atomic_dec_return(&tcpSesAllocCount);
989 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700990 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400991}
992
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400993static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400994standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
995{
996 int length;
997 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +1000998 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400999
1000 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001001 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
1002 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001003 cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001004 cifs_reconnect(server);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +04001005 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001006 }
1007
1008 /* switch to large buffer if too big for a small one */
1009 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
1010 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001011 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001012 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001013 }
1014
1015 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001016 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001017 pdu_length - HEADER_SIZE(server) + 1
1018 + server->vals->header_preamble_size);
1019
Jeff Laytone9097ab2011-10-19 15:29:40 -04001020 if (length < 0)
1021 return length;
1022 server->total_read += length;
1023
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001024 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001025
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08001026 return cifs_handle_standard(server, mid);
1027}
1028
1029int
1030cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1031{
1032 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1033 int length;
1034
Jeff Laytone9097ab2011-10-19 15:29:40 -04001035 /*
1036 * We know that we received enough to get to the MID as we
1037 * checked the pdu_length earlier. Now check to see
1038 * if the rest of the header is OK. We borrow the length
1039 * var for the rest of the loop to avoid a new stack var.
1040 *
1041 * 48 bytes is enough to display the header and a little bit
1042 * into the payload for debugging purposes.
1043 */
Steve French373512e2015-12-18 13:05:30 -06001044 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001045 if (length != 0)
1046 cifs_dump_mem("Bad SMB: ", buf,
1047 min_t(unsigned int, server->total_read, 48));
1048
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001049 if (server->ops->is_session_expired &&
1050 server->ops->is_session_expired(buf)) {
1051 cifs_reconnect(server);
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001052 return -1;
1053 }
1054
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001055 if (server->ops->is_status_pending &&
Pavel Shilovsky66265f12019-01-23 17:11:16 -08001056 server->ops->is_status_pending(buf, server))
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001057 return -1;
1058
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001059 if (!mid)
1060 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001061
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001062 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001063 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001064}
1065
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001066static void
1067smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
1068{
1069 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
1070
1071 /*
1072 * SMB1 does not use credits.
1073 */
1074 if (server->vals->header_preamble_size)
1075 return;
1076
1077 if (shdr->CreditRequest) {
1078 spin_lock(&server->req_lock);
1079 server->credits += le16_to_cpu(shdr->CreditRequest);
1080 spin_unlock(&server->req_lock);
1081 wake_up(&server->request_q);
1082 }
1083}
1084
1085
Jeff Laytone9097ab2011-10-19 15:29:40 -04001086static int
Al Viro7c97c202011-06-21 08:51:28 -04001087cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001089 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001090 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001091 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001092 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001093 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001094 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001095 struct mid_q_entry *mids[MAX_COMPOUND];
1096 char *bufs[MAX_COMPOUND];
Rohith Surabattula8e670f72020-09-18 05:37:28 +00001097 unsigned int noreclaim_flag, num_io_timeout = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
Eric Biggersdc920272020-03-08 22:58:20 -07001099 noreclaim_flag = memalloc_noreclaim_save();
Joe Perchesf96637b2013-05-04 22:12:25 -05001100 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001101
1102 length = atomic_inc_return(&tcpSesAllocCount);
1103 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001104 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001106 set_freezable();
Eric W. Biederman33da8e72019-08-16 12:33:54 -05001107 allow_kernel_signal(SIGKILL);
Jeff Layton469ee612008-10-16 18:46:39 +00001108 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001109 if (try_to_freeze())
1110 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001111
Jeff Layton2a37ef92011-10-19 15:29:23 -04001112 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001113 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001114
Jeff Layton2a37ef92011-10-19 15:29:23 -04001115 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001116 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001117 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001118
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001119 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001120 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001121 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001122
1123 if (server->vals->header_preamble_size == 0)
1124 server->total_read = 0;
1125 else
1126 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001127
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001128 /*
1129 * The right amount was read from socket - 4 bytes,
1130 * so we can now interpret the length field.
1131 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001132 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001133
Joe Perchesf96637b2013-05-04 22:12:25 -05001134 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001135 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001136 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001137next_pdu:
1138 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001139
Jeff Layton89482a52011-10-19 15:28:57 -04001140 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001141 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001142 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001143 cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001144 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001145 cifs_reconnect(server);
Jeff Layton89482a52011-10-19 15:28:57 -04001146 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001147 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001148
Jeff Layton89482a52011-10-19 15:28:57 -04001149 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001150 length = cifs_read_from_socket(server,
1151 buf + server->vals->header_preamble_size,
1152 HEADER_SIZE(server) - 1
1153 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001154 if (length < 0)
1155 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001156 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001157
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001158 if (server->ops->next_header) {
1159 next_offset = server->ops->next_header(buf);
1160 if (next_offset)
1161 server->pdu_size = next_offset;
1162 }
1163
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001164 memset(mids, 0, sizeof(mids));
1165 memset(bufs, 0, sizeof(bufs));
1166 num_mids = 0;
1167
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001168 if (server->ops->is_transform_hdr &&
1169 server->ops->receive_transform &&
1170 server->ops->is_transform_hdr(buf)) {
1171 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001172 mids,
1173 bufs,
1174 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001175 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001176 mids[0] = server->ops->find_mid(server, buf);
1177 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001178 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001179
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001180 if (!mids[0] || !mids[0]->receive)
1181 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001182 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001183 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001184 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001185
Lars Persson696e4202018-06-25 14:05:25 +02001186 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001187 for (i = 0; i < num_mids; i++)
1188 if (mids[i])
1189 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001190 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001191 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001192
Rohith Surabattula8e670f72020-09-18 05:37:28 +00001193 if (server->ops->is_status_io_timeout &&
1194 server->ops->is_status_io_timeout(buf)) {
1195 num_io_timeout++;
1196 if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
1197 cifs_reconnect(server);
1198 num_io_timeout = 0;
1199 continue;
1200 }
1201 }
1202
Steve Frenchfda35942011-01-20 18:06:34 +00001203 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001204
1205 for (i = 0; i < num_mids; i++) {
1206 if (mids[i] != NULL) {
1207 mids[i]->resp_buf_size = server->pdu_size;
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001208
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001209 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1210 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001211
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001212 cifs_mid_q_entry_release(mids[i]);
1213 } else if (server->ops->is_oplock_break &&
1214 server->ops->is_oplock_break(bufs[i],
1215 server)) {
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001216 smb2_add_credits_from_hdr(bufs[i], server);
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001217 cifs_dbg(FYI, "Received oplock break\n");
1218 } else {
Joe Perchesa0a30362020-04-14 22:42:53 -07001219 cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
1220 atomic_read(&midCount));
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001221 cifs_dump_mem("Received Data is: ", bufs[i],
1222 HEADER_SIZE(server));
Ronnie Sahlberg3e272572019-07-06 06:43:08 +10001223 smb2_add_credits_from_hdr(bufs[i], server);
Steve French39798772006-05-31 22:40:51 +00001224#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001225 if (server->ops->dump_detail)
1226 server->ops->dump_detail(bufs[i],
1227 server);
1228 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001229#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001230 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001231 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001232
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001233 if (pdu_length > server->pdu_size) {
1234 if (!allocate_buffers(server))
1235 continue;
1236 pdu_length -= server->pdu_size;
1237 server->total_read = 0;
1238 server->large_buf = false;
1239 buf = server->smallbuf;
1240 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001241 }
1242 } /* end while !EXITING */
1243
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001244 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001245 cifs_buf_release(server->bigbuf);
1246 if (server->smallbuf) /* no sense logging a debug message if NULL */
1247 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001249 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001250 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001251
1252 /* if server->tsk was NULL then wait for a signal before exiting */
1253 if (!task_to_wake) {
1254 set_current_state(TASK_INTERRUPTIBLE);
1255 while (!signal_pending(current)) {
1256 schedule();
1257 set_current_state(TASK_INTERRUPTIBLE);
1258 }
1259 set_current_state(TASK_RUNNING);
1260 }
1261
Eric Biggersdc920272020-03-08 22:58:20 -07001262 memalloc_noreclaim_restore(noreclaim_flag);
Jeff Layton0468a2c2008-12-01 07:09:35 -05001263 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264}
1265
Jeff Laytonc359cf32007-11-16 22:22:06 +00001266/* extract the host portion of the UNC string */
1267static char *
1268extract_hostname(const char *unc)
1269{
1270 const char *src;
1271 char *dst, *delim;
1272 unsigned int len;
1273
1274 /* skip double chars at beginning of string */
1275 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001276 if (strlen(unc) < 3)
1277 return ERR_PTR(-EINVAL);
1278 for (src = unc; *src && *src == '\\'; src++)
1279 ;
1280 if (!*src)
1281 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001282
1283 /* delimiter between hostname and sharename is always '\\' now */
1284 delim = strchr(src, '\\');
1285 if (!delim)
1286 return ERR_PTR(-EINVAL);
1287
1288 len = delim - src;
1289 dst = kmalloc((len + 1), GFP_KERNEL);
1290 if (dst == NULL)
1291 return ERR_PTR(-ENOMEM);
1292
1293 memcpy(dst, src, len);
1294 dst[len] = '\0';
1295
1296 return dst;
1297}
1298
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001299static int get_option_ul(substring_t args[], unsigned long *option)
1300{
1301 int rc;
1302 char *string;
1303
1304 string = match_strdup(args);
1305 if (string == NULL)
1306 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001307 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001308 kfree(string);
1309
1310 return rc;
1311}
1312
Eric W. Biederman3da46562013-02-06 01:37:39 -08001313static int get_option_uid(substring_t args[], kuid_t *result)
1314{
1315 unsigned long value;
1316 kuid_t uid;
1317 int rc;
1318
1319 rc = get_option_ul(args, &value);
1320 if (rc)
1321 return rc;
1322
1323 uid = make_kuid(current_user_ns(), value);
1324 if (!uid_valid(uid))
1325 return -EINVAL;
1326
1327 *result = uid;
1328 return 0;
1329}
1330
1331static int get_option_gid(substring_t args[], kgid_t *result)
1332{
1333 unsigned long value;
1334 kgid_t gid;
1335 int rc;
1336
1337 rc = get_option_ul(args, &value);
1338 if (rc)
1339 return rc;
1340
1341 gid = make_kgid(current_user_ns(), value);
1342 if (!gid_valid(gid))
1343 return -EINVAL;
1344
1345 *result = gid;
1346 return 0;
1347}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001350cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1351{
1352 substring_t args[MAX_OPT_ARGS];
1353
1354 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1355 case Opt_cache_loose:
1356 vol->direct_io = false;
1357 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001358 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001359 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001360 break;
1361 case Opt_cache_strict:
1362 vol->direct_io = false;
1363 vol->strict_io = true;
Steve French83bbfa72019-08-27 23:58:54 -05001364 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001365 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001366 break;
1367 case Opt_cache_none:
1368 vol->direct_io = true;
1369 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001370 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001371 vol->cache_rw = false;
Steve French83bbfa72019-08-27 23:58:54 -05001372 break;
1373 case Opt_cache_ro:
1374 vol->direct_io = false;
1375 vol->strict_io = false;
1376 vol->cache_ro = true;
Steve French41e033f2019-08-30 02:12:41 -05001377 vol->cache_rw = false;
1378 break;
1379 case Opt_cache_rw:
1380 vol->direct_io = false;
1381 vol->strict_io = false;
1382 vol->cache_ro = false;
1383 vol->cache_rw = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001384 break;
1385 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001386 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001387 return 1;
1388 }
1389 return 0;
1390}
1391
1392static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001393cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001394{
1395 substring_t args[MAX_OPT_ARGS];
1396
1397 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001398#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001399 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001400 if (disable_legacy_dialects) {
1401 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1402 return 1;
1403 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001404 if (is_smb3) {
1405 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1406 return 1;
1407 }
Joe Perchesa0a30362020-04-14 22:42:53 -07001408 cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
Jeff Layton23db65f2012-05-15 12:20:51 -04001409 vol->ops = &smb1_operations;
1410 vol->vals = &smb1_values;
1411 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001412 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001413 if (disable_legacy_dialects) {
1414 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1415 return 1;
1416 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001417 if (is_smb3) {
1418 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1419 return 1;
1420 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001421 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001422 vol->vals = &smb20_values;
1423 break;
Steve French74204512018-06-19 14:34:08 -05001424#else
1425 case Smb_1:
1426 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1427 return 1;
1428 case Smb_20:
1429 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1430 return 1;
1431#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001432 case Smb_21:
1433 vol->ops = &smb21_operations;
1434 vol->vals = &smb21_values;
1435 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001436 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001437 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001438 vol->vals = &smb30_values;
1439 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001440 case Smb_302:
1441 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1442 vol->vals = &smb302_values;
1443 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001444 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001445 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001446 vol->vals = &smb311_values;
1447 break;
Steve French9764c022017-09-17 10:41:35 -05001448 case Smb_3any:
1449 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1450 vol->vals = &smb3any_values;
1451 break;
1452 case Smb_default:
1453 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1454 vol->vals = &smbdefault_values;
1455 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001456 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001457 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001458 return 1;
1459 }
1460 return 0;
1461}
1462
Jeff Laytond387a5c2012-12-10 06:10:46 -05001463/*
1464 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1465 * fields with the result. Returns 0 on success and an error otherwise.
1466 */
1467static int
1468cifs_parse_devname(const char *devname, struct smb_vol *vol)
1469{
1470 char *pos;
1471 const char *delims = "/\\";
1472 size_t len;
1473
Yao Liu68e26722019-01-28 19:47:28 +08001474 if (unlikely(!devname || !*devname)) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001475 cifs_dbg(VFS, "Device name not specified\n");
Yao Liu68e26722019-01-28 19:47:28 +08001476 return -EINVAL;
1477 }
1478
Jeff Laytond387a5c2012-12-10 06:10:46 -05001479 /* make sure we have a valid UNC double delimiter prefix */
1480 len = strspn(devname, delims);
1481 if (len != 2)
1482 return -EINVAL;
1483
1484 /* find delimiter between host and sharename */
1485 pos = strpbrk(devname + 2, delims);
1486 if (!pos)
1487 return -EINVAL;
1488
1489 /* skip past delimiter */
1490 ++pos;
1491
1492 /* now go until next delimiter or end of string */
1493 len = strcspn(pos, delims);
1494
1495 /* move "pos" up to delimiter or NULL */
1496 pos += len;
1497 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1498 if (!vol->UNC)
1499 return -ENOMEM;
1500
1501 convert_delimiter(vol->UNC, '\\');
1502
Sachin Prabhu11e31642016-02-08 13:44:01 +05301503 /* skip any delimiter */
1504 if (*pos == '/' || *pos == '\\')
1505 pos++;
1506
1507 /* If pos is NULL then no prepath */
1508 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001509 return 0;
1510
1511 vol->prepath = kstrdup(pos, GFP_KERNEL);
1512 if (!vol->prepath)
1513 return -ENOMEM;
1514
1515 return 0;
1516}
1517
Jeff Layton23db65f2012-05-15 12:20:51 -04001518static int
Sean Finneyb9468452011-04-11 13:19:32 +00001519cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001520 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001522 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001523 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 unsigned int temp_len, i, j;
1525 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001526 short int override_uid = -1;
1527 short int override_gid = -1;
1528 bool uid_specified = false;
1529 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001530 bool sloppy = false;
1531 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001532 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001533 char *string = NULL;
1534 char *tmp_end, *value;
1535 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001536 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001537 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001538 unsigned short port = 0;
1539 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540
1541 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001542 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001543 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544
Jeff Layton6ee95422012-11-26 11:09:57 -05001545 /* ensure we always start with zeroed-out smb_vol */
1546 memset(vol, 0, sizeof(*vol));
1547
Jeff Layton88463992010-11-22 15:31:03 -05001548 /*
1549 * does not have to be perfect mapping since field is
1550 * informational, only used for servers that do not support
1551 * port 445 and it can be overridden at mount time
1552 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001553 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1554 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001555 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1556
Jeff Layton1397f2e2011-01-07 11:30:28 -05001557 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001558 /* null target name indicates to use *SMBSERVR default called name
1559 if we end up sending RFC1001 session initialize */
1560 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001561 vol->cred_uid = current_uid();
1562 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001563 vol->linux_gid = current_gid();
Steve Frenche8506d22019-02-28 21:32:15 -06001564 vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
Steve French2baa2682014-09-27 02:19:01 -05001565 /*
1566 * default to SFM style remapping of seven reserved characters
1567 * unless user overrides it or we negotiate CIFS POSIX where
1568 * it is unnecessary. Can not simultaneously use more than one mapping
1569 * since then readdir could list files that open could not open
1570 */
1571 vol->remap = true;
1572
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001573 /* default to only allowing write access to owner of the mount */
1574 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575
1576 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001577 /* default is always to request posix paths. */
1578 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001579 /* default to using server inode numbers where available */
1580 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001581
Jeff Layton1b359202012-09-19 15:20:27 -07001582 /* default is to use strict cifs caching semantics */
1583 vol->strict_io = true;
1584
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301585 vol->actimeo = CIFS_DEF_ACTIMEO;
1586
Steve Frenchca567eb2019-03-29 16:31:07 -05001587 /* Most clients set timeout to 0, allows server to use its default */
1588 vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1589
Steve French9764c022017-09-17 10:41:35 -05001590 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1591 vol->ops = &smb30_operations;
1592 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001593
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001594 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1595
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001596 /* default to no multichannel (single server connection) */
1597 vol->multichannel = false;
1598 vol->max_channels = 1;
1599
Sean Finneyb9468452011-04-11 13:19:32 +00001600 if (!mountdata)
1601 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
Sean Finneyb9468452011-04-11 13:19:32 +00001603 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1604 if (!mountdata_copy)
1605 goto cifs_parse_mount_err;
1606
1607 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001608 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001609
Steve French50c2f752007-07-13 00:33:32 +00001610 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001611 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 separator[0] = options[4];
1613 options += 5;
1614 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001615 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 }
1617 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001618 vol->backupuid_specified = false; /* no backup intent for a user */
1619 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001620
Jeff Layton37d4f992013-05-24 07:40:05 -04001621 switch (cifs_parse_devname(devname, vol)) {
1622 case 0:
1623 break;
1624 case -ENOMEM:
Joe Perchesa0a30362020-04-14 22:42:53 -07001625 cifs_dbg(VFS, "Unable to allocate memory for devname\n");
Jeff Layton37d4f992013-05-24 07:40:05 -04001626 goto cifs_parse_mount_err;
1627 case -EINVAL:
Joe Perchesa0a30362020-04-14 22:42:53 -07001628 cifs_dbg(VFS, "Malformed UNC in devname\n");
Jeff Layton37d4f992013-05-24 07:40:05 -04001629 goto cifs_parse_mount_err;
1630 default:
Joe Perchesa0a30362020-04-14 22:42:53 -07001631 cifs_dbg(VFS, "Unknown error parsing devname\n");
Jeff Layton37d4f992013-05-24 07:40:05 -04001632 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001633 }
1634
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001636 substring_t args[MAX_OPT_ARGS];
1637 unsigned long option;
1638 int token;
1639
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 if (!*data)
1641 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001643 token = match_token(data, cifs_mount_option_tokens, args);
1644
1645 switch (token) {
1646
1647 /* Ingnore the following */
1648 case Opt_ignore:
1649 break;
1650
1651 /* Boolean values */
1652 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001654 break;
1655 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001657 break;
1658 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001659 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001660 break;
1661 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001662 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001663 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001664 case Opt_forcegid:
1665 override_gid = 1;
1666 break;
1667 case Opt_noforcegid:
1668 override_gid = 0;
1669 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001670 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001671 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001672 break;
1673 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001674 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001675 break;
Steve French3e7a02d2019-09-11 21:46:20 -05001676 case Opt_nolease:
1677 vol->no_lease = 1;
1678 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001679 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001681 break;
1682 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001684 break;
1685 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001687 break;
1688 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001690 break;
Steve French82e93672020-05-19 03:06:57 -05001691 case Opt_nodelete:
1692 vol->nodelete = 1;
1693 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001694 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001695 vol->sfu_remap = true;
1696 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001697 break;
1698 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001699 vol->sfu_remap = false;
1700 break;
1701 case Opt_mapposix:
1702 vol->remap = true;
1703 vol->sfu_remap = false; /* disable SFU mapping */
1704 break;
1705 case Opt_nomapposix:
1706 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001707 break;
1708 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001709 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001710 break;
1711 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001712 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001713 break;
1714 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001715 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001716 break;
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03001717 case Opt_rootfs:
1718#ifdef CONFIG_CIFS_ROOT
1719 vol->rootfs = true;
1720#endif
1721 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001722 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001723 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001724 break;
1725 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001726 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001727 break;
1728 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001729 if (vol->linux_ext)
1730 cifs_dbg(VFS,
1731 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001732 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001733 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001734 case Opt_unix:
1735 if (vol->no_linux_ext)
1736 cifs_dbg(VFS,
1737 "conflicting unix mount options\n");
1738 vol->linux_ext = 1;
1739 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001740 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001741 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001742 break;
1743 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001744 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 break;
1746 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001747 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001748 /*
1749 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001750 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001751 * local vfs will do advisory
1752 */
Steve French50c2f752007-07-13 00:33:32 +00001753 if (vol->file_mode ==
1754 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001755 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001756 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001757 case Opt_nohandlecache:
1758 vol->nohandlecache = 1;
1759 break;
1760 case Opt_handlecache:
1761 vol->nohandlecache = 0;
1762 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001763 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001764 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001765 break;
1766 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001768 break;
1769 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001771 break;
Steve French95932652016-09-23 01:36:34 -05001772 case Opt_setuidfromacl:
1773 vol->setuidfromacl = 1;
1774 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001775 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001776 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001777 break;
1778 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001779 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001780 break;
1781 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001783 break;
1784 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001786 break;
1787 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001789 break;
1790 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001792 break;
1793 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001794 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001795 break;
1796 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001797 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001798 break;
1799 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001801 break;
1802 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001804 break;
1805 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001806 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001807 break;
Steve French412094a2019-06-24 02:01:42 -05001808 case Opt_modesid:
1809 vol->mode_ace = 1;
1810 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001811 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001812 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001813 break;
1814 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001815 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001816 break;
1817 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001819 break;
1820 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001822 break;
1823 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001824 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001825 break;
1826 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001827 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001828 break;
Steve French4f5c10f2019-09-03 21:18:49 -05001829 case Opt_ignore_signature:
1830 vol->sign = true;
1831 vol->ignore_signature = true;
1832 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001833 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001834 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001835 * is a per tree connection (mount) not a per socket
1836 * or per-smb connection option in the protocol
1837 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1838 */
Steve French95b1cb92008-05-15 16:44:38 +00001839 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001840 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001841 case Opt_noac:
Joe Perchesa0a30362020-04-14 22:42:53 -07001842 pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001843 break;
1844 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301845#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001846 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001847 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301848#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301849 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001850 break;
1851 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001852 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001853 break;
1854 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001855 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001856 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001857 case Opt_sloppy:
1858 sloppy = true;
1859 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001860 case Opt_nosharesock:
1861 vol->nosharesock = true;
1862 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001863 case Opt_nopersistent:
1864 vol->nopersistent = true;
1865 if (vol->persistent) {
1866 cifs_dbg(VFS,
1867 "persistenthandles mount options conflict\n");
1868 goto cifs_parse_mount_err;
1869 }
1870 break;
1871 case Opt_persistent:
1872 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001873 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001874 cifs_dbg(VFS,
1875 "persistenthandles mount options conflict\n");
1876 goto cifs_parse_mount_err;
1877 }
1878 break;
Steve French592fafe2015-11-03 10:08:53 -06001879 case Opt_resilient:
1880 vol->resilient = true;
1881 if (vol->persistent) {
1882 cifs_dbg(VFS,
1883 "persistenthandles mount options conflict\n");
1884 goto cifs_parse_mount_err;
1885 }
1886 break;
1887 case Opt_noresilient:
1888 vol->resilient = false; /* already the default */
1889 break;
Germano Percossi39566442016-12-15 12:31:18 +05301890 case Opt_domainauto:
1891 vol->domainauto = true;
1892 break;
Long Li8339dd32017-11-07 01:54:55 -07001893 case Opt_rdma:
1894 vol->rdma = true;
1895 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001896 case Opt_multichannel:
1897 vol->multichannel = true;
Steve French1ee0e6d2020-06-02 23:17:16 -05001898 /* if number of channels not specified, default to 2 */
1899 if (vol->max_channels < 2)
1900 vol->max_channels = 2;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001901 break;
1902 case Opt_nomultichannel:
1903 vol->multichannel = false;
Steve French1ee0e6d2020-06-02 23:17:16 -05001904 vol->max_channels = 1;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001905 break;
Steve French9fe5ff12019-06-24 20:39:04 -05001906 case Opt_compress:
1907 vol->compression = UNKNOWN_TYPE;
1908 cifs_dbg(VFS,
1909 "SMB3 compression support is experimental\n");
1910 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001911
1912 /* Numeric Values */
1913 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001914 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001915 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1916 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001917 goto cifs_parse_mount_err;
1918 }
1919 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001920 break;
1921 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001922 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001923 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1924 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001925 goto cifs_parse_mount_err;
1926 }
1927 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001928 break;
1929 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001930 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001931 cifs_dbg(VFS, "%s: Invalid uid value\n",
1932 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001933 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001935 uid_specified = true;
1936 break;
1937 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001938 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001939 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1940 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001941 goto cifs_parse_mount_err;
1942 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001943 break;
1944 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001945 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001946 cifs_dbg(VFS, "%s: Invalid gid value\n",
1947 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001948 goto cifs_parse_mount_err;
1949 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001950 gid_specified = true;
1951 break;
1952 case Opt_file_mode:
1953 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001954 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1955 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001956 goto cifs_parse_mount_err;
1957 }
1958 vol->file_mode = option;
1959 break;
1960 case Opt_dirmode:
1961 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001962 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1963 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001964 goto cifs_parse_mount_err;
1965 }
1966 vol->dir_mode = option;
1967 break;
1968 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001969 if (get_option_ul(args, &option) ||
1970 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001971 cifs_dbg(VFS, "%s: Invalid port value\n",
1972 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001973 goto cifs_parse_mount_err;
1974 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001975 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001976 break;
Steve French563317e2019-09-08 23:22:02 -05001977 case Opt_min_enc_offload:
1978 if (get_option_ul(args, &option)) {
1979 cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
1980 goto cifs_parse_mount_err;
1981 }
1982 vol->min_offload = option;
1983 break;
Steve Frenche8506d22019-02-28 21:32:15 -06001984 case Opt_blocksize:
1985 if (get_option_ul(args, &option)) {
1986 cifs_dbg(VFS, "%s: Invalid blocksize value\n",
1987 __func__);
1988 goto cifs_parse_mount_err;
1989 }
1990 /*
1991 * inode blocksize realistically should never need to be
1992 * less than 16K or greater than 16M and default is 1MB.
1993 * Note that small inode block sizes (e.g. 64K) can lead
1994 * to very poor performance of common tools like cp and scp
1995 */
1996 if ((option < CIFS_MAX_MSGSIZE) ||
1997 (option > (4 * SMB3_DEFAULT_IOSIZE))) {
1998 cifs_dbg(VFS, "%s: Invalid blocksize\n",
1999 __func__);
2000 goto cifs_parse_mount_err;
2001 }
2002 vol->bsize = option;
2003 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002004 case Opt_rsize:
2005 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002006 cifs_dbg(VFS, "%s: Invalid rsize value\n",
2007 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002008 goto cifs_parse_mount_err;
2009 }
2010 vol->rsize = option;
2011 break;
2012 case Opt_wsize:
2013 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002014 cifs_dbg(VFS, "%s: Invalid wsize value\n",
2015 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002016 goto cifs_parse_mount_err;
2017 }
2018 vol->wsize = option;
2019 break;
2020 case Opt_actimeo:
2021 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002022 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
2023 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002024 goto cifs_parse_mount_err;
2025 }
2026 vol->actimeo = HZ * option;
2027 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002028 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002029 goto cifs_parse_mount_err;
2030 }
2031 break;
Steve Frenchca567eb2019-03-29 16:31:07 -05002032 case Opt_handletimeout:
2033 if (get_option_ul(args, &option)) {
2034 cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
2035 __func__);
2036 goto cifs_parse_mount_err;
2037 }
2038 vol->handle_timeout = option;
2039 if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
2040 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
2041 goto cifs_parse_mount_err;
2042 }
2043 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002044 case Opt_echo_interval:
2045 if (get_option_ul(args, &option)) {
2046 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
2047 __func__);
2048 goto cifs_parse_mount_err;
2049 }
2050 vol->echo_interval = option;
2051 break;
Steve French8b217fe2016-11-11 22:36:20 -06002052 case Opt_snapshot:
2053 if (get_option_ul(args, &option)) {
2054 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
2055 __func__);
2056 goto cifs_parse_mount_err;
2057 }
2058 vol->snapshot_time = option;
2059 break;
Steve French141891f2016-09-23 00:44:16 -05002060 case Opt_max_credits:
2061 if (get_option_ul(args, &option) || (option < 20) ||
2062 (option > 60000)) {
2063 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
2064 __func__);
2065 goto cifs_parse_mount_err;
2066 }
2067 vol->max_credits = option;
2068 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002069 case Opt_max_channels:
2070 if (get_option_ul(args, &option) || option < 1 ||
2071 option > CIFS_MAX_CHANNELS) {
2072 cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
2073 __func__, CIFS_MAX_CHANNELS);
2074 goto cifs_parse_mount_err;
2075 }
2076 vol->max_channels = option;
2077 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002078
2079 /* String Arguments */
2080
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002081 case Opt_blank_user:
2082 /* null user, ie. anonymous authentication */
2083 vol->nullauth = 1;
2084 vol->username = NULL;
2085 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002086 case Opt_user:
2087 string = match_strdup(args);
2088 if (string == NULL)
2089 goto out_nomem;
2090
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002091 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
2092 CIFS_MAX_USERNAME_LEN) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002093 pr_warn("username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002094 goto cifs_parse_mount_err;
2095 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002096
2097 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002098 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05002099 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002100 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002101 break;
2102 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002103 /* passwords have to be handled differently
2104 * to allow the character used for deliminator
2105 * to be passed within them
2106 */
2107
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002108 /*
2109 * Check if this is a case where the password
2110 * starts with a delimiter
2111 */
2112 tmp_end = strchr(data, '=');
2113 tmp_end++;
2114 if (!(tmp_end < end && tmp_end[1] == delim)) {
2115 /* No it is not. Set the password to NULL */
Waiman Long453431a2020-08-06 23:18:13 -07002116 kfree_sensitive(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002117 vol->password = NULL;
2118 break;
2119 }
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05002120 fallthrough; /* to Opt_pass below */
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002121 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002122 /* Obtain the value string */
2123 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002124 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002125
2126 /* Set tmp_end to end of the string */
2127 tmp_end = (char *) value + strlen(value);
2128
2129 /* Check if following character is the deliminator
2130 * If yes, we have encountered a double deliminator
2131 * reset the NULL character to the deliminator
2132 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302133 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002134 tmp_end[0] = delim;
2135
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302136 /* Keep iterating until we get to a single
2137 * deliminator OR the end
2138 */
2139 while ((tmp_end = strchr(tmp_end, delim))
2140 != NULL && (tmp_end[1] == delim)) {
2141 tmp_end = (char *) &tmp_end[2];
2142 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002143
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302144 /* Reset var options to point to next element */
2145 if (tmp_end) {
2146 tmp_end[0] = '\0';
2147 options = (char *) &tmp_end[1];
2148 } else
2149 /* Reached the end of the mount option
2150 * string */
2151 options = end;
2152 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002153
Waiman Long453431a2020-08-06 23:18:13 -07002154 kfree_sensitive(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002155 /* Now build new password string */
2156 temp_len = strlen(value);
2157 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2158 if (vol->password == NULL) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002159 pr_warn("no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002160 goto cifs_parse_mount_err;
2161 }
2162
2163 for (i = 0, j = 0; i < temp_len; i++, j++) {
2164 vol->password[j] = value[i];
2165 if ((value[i] == delim) &&
2166 value[i+1] == delim)
2167 /* skip the second deliminator */
2168 i++;
2169 }
2170 vol->password[j] = '\0';
2171 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002172 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002173 /* FIXME: should this be an error instead? */
2174 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002175 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002176 case Opt_ip:
2177 string = match_strdup(args);
2178 if (string == NULL)
2179 goto out_nomem;
2180
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002181 if (!cifs_convert_address(dstaddr, string,
2182 strlen(string))) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002183 pr_err("bad ip= option (%s)\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002184 goto cifs_parse_mount_err;
2185 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002186 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002187 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002188 case Opt_domain:
2189 string = match_strdup(args);
2190 if (string == NULL)
2191 goto out_nomem;
2192
Chen Gang057d6332013-07-19 09:01:36 +08002193 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2194 == CIFS_MAX_DOMAINNAME_LEN) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002195 pr_warn("domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002196 goto cifs_parse_mount_err;
2197 }
2198
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002199 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002200 vol->domainname = kstrdup(string, GFP_KERNEL);
2201 if (!vol->domainname) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002202 pr_warn("no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002203 goto cifs_parse_mount_err;
2204 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002205 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002206 break;
2207 case Opt_srcaddr:
2208 string = match_strdup(args);
2209 if (string == NULL)
2210 goto out_nomem;
2211
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002212 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002213 (struct sockaddr *)&vol->srcaddr,
2214 string, strlen(string))) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002215 pr_warn("Could not parse srcaddr: %s\n",
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002216 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002217 goto cifs_parse_mount_err;
2218 }
2219 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002220 case Opt_iocharset:
2221 string = match_strdup(args);
2222 if (string == NULL)
2223 goto out_nomem;
2224
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002225 if (strnlen(string, 1024) >= 65) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002226 pr_warn("iocharset name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002227 goto cifs_parse_mount_err;
2228 }
2229
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002230 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002231 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002232 vol->iocharset = kstrdup(string,
2233 GFP_KERNEL);
2234 if (!vol->iocharset) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002235 pr_warn("no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002236 goto cifs_parse_mount_err;
2237 }
2238 }
2239 /* if iocharset not set then load_nls_default
2240 * is used by caller
2241 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002242 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002243 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002244 case Opt_netbiosname:
2245 string = match_strdup(args);
2246 if (string == NULL)
2247 goto out_nomem;
2248
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002249 memset(vol->source_rfc1001_name, 0x20,
2250 RFC1001_NAME_LEN);
2251 /*
2252 * FIXME: are there cases in which a comma can
2253 * be valid in workstation netbios name (and
2254 * need special handling)?
2255 */
2256 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2257 /* don't ucase netbiosname for user */
2258 if (string[i] == 0)
2259 break;
2260 vol->source_rfc1001_name[i] = string[i];
2261 }
2262 /* The string has 16th byte zero still from
2263 * set at top of the function
2264 */
2265 if (i == RFC1001_NAME_LEN && string[i] != 0)
Joe Perchesa0a30362020-04-14 22:42:53 -07002266 pr_warn("netbiosname longer than 15 truncated\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002267 break;
2268 case Opt_servern:
2269 /* servernetbiosname specified override *SMBSERVER */
2270 string = match_strdup(args);
2271 if (string == NULL)
2272 goto out_nomem;
2273
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002274 /* last byte, type, is 0x20 for servr type */
2275 memset(vol->target_rfc1001_name, 0x20,
2276 RFC1001_NAME_LEN_WITH_NULL);
2277
2278 /* BB are there cases in which a comma can be
2279 valid in this workstation netbios name
2280 (and need special handling)? */
2281
2282 /* user or mount helper must uppercase the
2283 netbios name */
2284 for (i = 0; i < 15; i++) {
2285 if (string[i] == 0)
2286 break;
2287 vol->target_rfc1001_name[i] = string[i];
2288 }
2289 /* The string has 16th byte zero still from
2290 set at top of the function */
2291 if (i == RFC1001_NAME_LEN && string[i] != 0)
Joe Perchesa0a30362020-04-14 22:42:53 -07002292 pr_warn("server netbiosname longer than 15 truncated\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002293 break;
2294 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002295 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002296 string = match_strdup(args);
2297 if (string == NULL)
2298 goto out_nomem;
2299
Steve French7e682f72017-08-31 21:34:24 -05002300 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002301 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002302 if (strlen(string) > 1) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002303 pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
2304 string);
Steve French7e682f72017-08-31 21:34:24 -05002305 goto cifs_parse_mount_err;
2306 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002307 /* This is the default */
2308 break;
2309 }
2310 /* For all other value, error */
Joe Perchesa0a30362020-04-14 22:42:53 -07002311 pr_warn("Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002312 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002313 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002314 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002315 string = match_strdup(args);
2316 if (string == NULL)
2317 goto out_nomem;
2318
Steve Frenchc7c137b2018-06-06 17:59:29 -05002319 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002320 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002321 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002322 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002323 case Opt_sec:
2324 string = match_strdup(args);
2325 if (string == NULL)
2326 goto out_nomem;
2327
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002328 if (cifs_parse_security_flavors(string, vol) != 0)
2329 goto cifs_parse_mount_err;
2330 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002331 case Opt_cache:
2332 string = match_strdup(args);
2333 if (string == NULL)
2334 goto out_nomem;
2335
2336 if (cifs_parse_cache_flavor(string, vol) != 0)
2337 goto cifs_parse_mount_err;
2338 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002339 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002340 /*
2341 * An option we don't recognize. Save it off for later
2342 * if we haven't already found one
2343 */
2344 if (!invalid)
2345 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002346 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002348 /* Free up any allocated string */
2349 kfree(string);
2350 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002352
Jeff Laytond8162552012-03-23 14:40:56 -04002353 if (!sloppy && invalid) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002354 pr_err("Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002355 goto cifs_parse_mount_err;
2356 }
2357
Long Li8339dd32017-11-07 01:54:55 -07002358 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2359 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2360 goto cifs_parse_mount_err;
2361 }
2362
Jeff Layton8a8798a2012-01-17 16:09:15 -05002363#ifndef CONFIG_KEYS
2364 /* Muliuser mounts require CONFIG_KEYS support */
2365 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002366 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002367 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002368 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002369#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002370 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002371 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002372 goto cifs_parse_mount_err;
2373 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002374
Jeff Layton62a1a432012-12-10 06:10:45 -05002375 /* make sure UNC has a share name */
2376 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002377 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002378 goto cifs_parse_mount_err;
2379 }
2380
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002381 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002382 int len;
2383 const char *slash;
2384
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002385 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002386 /* Use the address part of the UNC. */
2387 slash = strchr(&vol->UNC[2], '\\');
2388 len = slash - &vol->UNC[2];
2389 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002390 pr_err("Unable to determine destination address\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002391 goto cifs_parse_mount_err;
2392 }
2393 }
2394
2395 /* set the port that we got earlier */
2396 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002398 if (uid_specified)
2399 vol->override_uid = override_uid;
2400 else if (override_uid == 1)
Joe Perchesa0a30362020-04-14 22:42:53 -07002401 pr_notice("ignoring forceuid mount option specified with no uid= option\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002402
2403 if (gid_specified)
2404 vol->override_gid = override_gid;
2405 else if (override_gid == 1)
Joe Perchesa0a30362020-04-14 22:42:53 -07002406 pr_notice("ignoring forcegid mount option specified with no gid= option\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002407
Steve French7e682f72017-08-31 21:34:24 -05002408 if (got_version == false)
Joe Perchesa0a30362020-04-14 22:42:53 -07002409 pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002410
Sean Finneyb9468452011-04-11 13:19:32 +00002411 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002413
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002414out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002415 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002416cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002417 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002418 kfree(mountdata_copy);
2419 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420}
2421
Ben Greear3eb9a882010-09-01 17:06:02 -07002422/** Returns true if srcaddr isn't specified and rhs isn't
2423 * specified, or if srcaddr is specified and
2424 * matches the IP address of the rhs argument.
2425 */
Paulo Alcantarae4af35f2020-05-19 15:38:28 -03002426bool
2427cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
Ben Greear3eb9a882010-09-01 17:06:02 -07002428{
2429 switch (srcaddr->sa_family) {
2430 case AF_UNSPEC:
2431 return (rhs->sa_family == AF_UNSPEC);
2432 case AF_INET: {
2433 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2434 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2435 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2436 }
2437 case AF_INET6: {
2438 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002439 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002440 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2441 }
2442 default:
2443 WARN_ON(1);
2444 return false; /* don't expect to be here */
2445 }
2446}
2447
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002448/*
2449 * If no port is specified in addr structure, we try to match with 445 port
2450 * and if it fails - with 139 ports. It should be called only if address
2451 * families of server and addr are equal.
2452 */
2453static bool
2454match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2455{
Steve French6da97912011-03-13 18:55:55 +00002456 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002457
Long Li3b249112019-05-15 14:09:04 -07002458 /* SMBDirect manages its own ports, don't match it here */
2459 if (server->rdma)
2460 return true;
2461
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002462 switch (addr->sa_family) {
2463 case AF_INET:
2464 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2465 port = ((struct sockaddr_in *) addr)->sin_port;
2466 break;
2467 case AF_INET6:
2468 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2469 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2470 break;
2471 default:
2472 WARN_ON(1);
2473 return false;
2474 }
2475
2476 if (!port) {
2477 port = htons(CIFS_PORT);
2478 if (port == *sport)
2479 return true;
2480
2481 port = htons(RFC1001_PORT);
2482 }
2483
2484 return port == *sport;
2485}
Ben Greear3eb9a882010-09-01 17:06:02 -07002486
2487static bool
2488match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2489 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490{
Jeff Layton45151482010-07-06 20:43:02 -04002491 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002492 case AF_INET: {
2493 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2494 struct sockaddr_in *srv_addr4 =
2495 (struct sockaddr_in *)&server->dstaddr;
2496
2497 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002498 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002499 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002500 }
2501 case AF_INET6: {
2502 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2503 struct sockaddr_in6 *srv_addr6 =
2504 (struct sockaddr_in6 *)&server->dstaddr;
2505
Jeff Layton45151482010-07-06 20:43:02 -04002506 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002507 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002508 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002509 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002510 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002511 break;
2512 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002513 default:
2514 WARN_ON(1);
2515 return false; /* don't expect to be here */
2516 }
Jeff Layton45151482010-07-06 20:43:02 -04002517
Paulo Alcantarae4af35f2020-05-19 15:38:28 -03002518 if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr))
Ben Greear3eb9a882010-09-01 17:06:02 -07002519 return false;
2520
Jeff Layton45151482010-07-06 20:43:02 -04002521 return true;
2522}
2523
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002524static bool
2525match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2526{
Jeff Layton3f618222013-06-12 19:52:14 -05002527 /*
2528 * The select_sectype function should either return the vol->sectype
2529 * that was specified, or "Unspecified" if that sectype was not
2530 * compatible with the given NEGOTIATE request.
2531 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302532 if (server->ops->select_sectype(server, vol->sectype)
2533 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002534 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002535
Jeff Layton3f618222013-06-12 19:52:14 -05002536 /*
2537 * Now check if signing mode is acceptable. No need to check
2538 * global_secflags at this point since if MUST_SIGN is set then
2539 * the server->sign had better be too.
2540 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002541 if (vol->sign && !server->sign)
2542 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002543
2544 return true;
2545}
2546
Jeff Layton9fa114f2012-11-26 11:09:57 -05002547static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002548{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002549 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2550
Jeff Laytona0b3df52013-05-24 07:40:59 -04002551 if (vol->nosharesock)
2552 return 0;
2553
Steve French43cdae82019-06-13 14:26:49 -05002554 /* If multidialect negotiation see if existing sessions match one */
2555 if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2556 if (server->vals->protocol_id < SMB30_PROT_ID)
2557 return 0;
2558 } else if (strcmp(vol->vals->version_string,
2559 SMBDEFAULT_VERSION_STRING) == 0) {
2560 if (server->vals->protocol_id < SMB21_PROT_ID)
2561 return 0;
2562 } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
Jeff Layton23db65f2012-05-15 12:20:51 -04002563 return 0;
2564
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002565 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2566 return 0;
2567
2568 if (!match_address(server, addr,
2569 (struct sockaddr *)&vol->srcaddr))
2570 return 0;
2571
2572 if (!match_port(server, addr))
2573 return 0;
2574
2575 if (!match_security(server, vol))
2576 return 0;
2577
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002578 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002579 return 0;
2580
Long Li8339dd32017-11-07 01:54:55 -07002581 if (server->rdma != vol->rdma)
2582 return 0;
2583
Steve French4f5c10f2019-09-03 21:18:49 -05002584 if (server->ignore_signature != vol->ignore_signature)
2585 return 0;
2586
Steve French563317e2019-09-08 23:22:02 -05002587 if (server->min_offload != vol->min_offload)
2588 return 0;
2589
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002590 return 1;
2591}
2592
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002593struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002594cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002595{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002596 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302598 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002599 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Paulo Alcantara (SUSE)3345bb42019-12-04 11:25:06 -03002600 /*
2601 * Skip ses channels since they're only handled in lower layers
2602 * (e.g. cifs_send_recv).
2603 */
2604 if (server->is_channel || !match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002605 continue;
2606
Jeff Laytone7ddee92008-11-14 13:44:38 -05002607 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302608 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002609 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002610 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302612 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 return NULL;
2614}
2615
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002616void
2617cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002619 struct task_struct *task;
2620
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302621 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002622 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302623 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002624 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002626
Rob Landleyf1d0c992011-01-22 15:44:05 -06002627 put_net(cifs_net_ns(server));
2628
Jeff Laytone7ddee92008-11-14 13:44:38 -05002629 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302630 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002631
Jeff Laytonc74093b2011-01-11 07:24:23 -05002632 cancel_delayed_work_sync(&server->echo);
2633
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002634 if (from_reconnect)
2635 /*
2636 * Avoid deadlock here: reconnect work calls
2637 * cifs_put_tcp_session() at its end. Need to be sure
2638 * that reconnect work does nothing with server pointer after
2639 * that step.
2640 */
2641 cancel_delayed_work(&server->reconnect);
2642 else
2643 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002644
Jeff Laytone7ddee92008-11-14 13:44:38 -05002645 spin_lock(&GlobalMid_Lock);
2646 server->tcpStatus = CifsExiting;
2647 spin_unlock(&GlobalMid_Lock);
2648
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002649 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302650 cifs_fscache_release_client_cookie(server);
2651
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002652 kfree(server->session_key.response);
2653 server->session_key.response = NULL;
2654 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002655
2656 task = xchg(&server->tsk, NULL);
2657 if (task)
Eric W. Biederman72abe3b2019-05-15 12:33:50 -05002658 send_sig(SIGKILL, task, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659}
2660
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02002661struct TCP_Server_Info *
Jeff Layton63c038c2008-12-01 18:41:46 -05002662cifs_get_tcp_session(struct smb_vol *volume_info)
2663{
2664 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002665 int rc;
2666
Joe Perchesf96637b2013-05-04 22:12:25 -05002667 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002668
2669 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002670 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002671 if (tcp_ses)
2672 return tcp_ses;
2673
2674 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2675 if (!tcp_ses) {
2676 rc = -ENOMEM;
2677 goto out_err;
2678 }
2679
Jeff Layton23db65f2012-05-15 12:20:51 -04002680 tcp_ses->ops = volume_info->ops;
2681 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002682 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002683 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2684 if (IS_ERR(tcp_ses->hostname)) {
2685 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002686 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002687 }
2688
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03002689 tcp_ses->noblockcnt = volume_info->rootfs;
2690 tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
Jeff Layton63c038c2008-12-01 18:41:46 -05002691 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002692 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002693 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002694 tcp_ses->in_flight = 0;
Steve French1b63f182019-09-09 22:57:11 -05002695 tcp_ses->max_in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002696 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002697 init_waitqueue_head(&tcp_ses->response_q);
2698 init_waitqueue_head(&tcp_ses->request_q);
2699 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2700 mutex_init(&tcp_ses->srv_mutex);
2701 memcpy(tcp_ses->workstation_RFC1001_name,
2702 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2703 memcpy(tcp_ses->server_RFC1001_name,
2704 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002705 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002706 tcp_ses->sequence_number = 0;
Pavel Shilovsky5b964852019-01-18 11:30:26 -08002707 tcp_ses->reconnect_instance = 1;
Steve Frenchfda35942011-01-20 18:06:34 +00002708 tcp_ses->lstrp = jiffies;
Steve French9fe5ff12019-06-24 20:39:04 -05002709 tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
Jeff Layton58fa0152012-05-01 17:41:16 -04002710 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002711 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2712 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002713 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002714 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2715 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002716 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2717 sizeof(tcp_ses->srcaddr));
2718 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2719 sizeof(tcp_ses->dstaddr));
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002720 if (volume_info->use_client_guid)
2721 memcpy(tcp_ses->client_guid, volume_info->client_guid,
2722 SMB2_CLIENT_GUID_SIZE);
2723 else
2724 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002725 /*
2726 * at this point we are the only ones with the pointer
2727 * to the struct since the kernel thread not created yet
2728 * no need to spinlock this init of tcpStatus or srv_count
2729 */
2730 tcp_ses->tcpStatus = CifsNew;
2731 ++tcp_ses->srv_count;
2732
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002733 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2734 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2735 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2736 else
2737 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002738 if (tcp_ses->rdma) {
2739#ifndef CONFIG_CIFS_SMB_DIRECT
2740 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2741 rc = -ENOENT;
2742 goto out_err_crypto_release;
2743#endif
2744 tcp_ses->smbd_conn = smbd_get_connection(
2745 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2746 if (tcp_ses->smbd_conn) {
2747 cifs_dbg(VFS, "RDMA transport established\n");
2748 rc = 0;
2749 goto smbd_connected;
2750 } else {
2751 rc = -ENOENT;
2752 goto out_err_crypto_release;
2753 }
2754 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002755 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002756 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002757 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002758 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002759 }
Long Li2f894642017-11-22 17:38:34 -07002760smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002761 /*
2762 * since we're in a cifs function already, we know that
2763 * this will succeed. No need for try_module_get().
2764 */
2765 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002766 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002767 tcp_ses, "cifsd");
2768 if (IS_ERR(tcp_ses->tsk)) {
2769 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002770 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002771 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002772 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002773 }
Steve French563317e2019-09-08 23:22:02 -05002774 tcp_ses->min_offload = volume_info->min_offload;
Steve Frenchfd88ce92011-04-12 01:01:14 +00002775 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002776
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002777 tcp_ses->nr_targets = 1;
Steve French4f5c10f2019-09-03 21:18:49 -05002778 tcp_ses->ignore_signature = volume_info->ignore_signature;
Jeff Layton63c038c2008-12-01 18:41:46 -05002779 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302780 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002781 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302782 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002783
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302784 cifs_fscache_get_client_cookie(tcp_ses);
2785
Jeff Laytonc74093b2011-01-11 07:24:23 -05002786 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002787 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002788
Jeff Layton63c038c2008-12-01 18:41:46 -05002789 return tcp_ses;
2790
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002791out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002792 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002793
Rob Landleyf1d0c992011-01-22 15:44:05 -06002794 put_net(cifs_net_ns(tcp_ses));
2795
Jeff Layton63c038c2008-12-01 18:41:46 -05002796out_err:
2797 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002798 if (!IS_ERR(tcp_ses->hostname))
2799 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002800 if (tcp_ses->ssocket)
2801 sock_release(tcp_ses->ssocket);
2802 kfree(tcp_ses);
2803 }
2804 return ERR_PTR(rc);
2805}
2806
Steve French96daf2b2011-05-27 04:34:02 +00002807static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002808{
Jeff Layton3f618222013-06-12 19:52:14 -05002809 if (vol->sectype != Unspecified &&
2810 vol->sectype != ses->sectype)
2811 return 0;
2812
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002813 /*
2814 * If an existing session is limited to less channels than
2815 * requested, it should not be reused
2816 */
2817 if (ses->chan_max < vol->max_channels)
2818 return 0;
2819
Jeff Layton3f618222013-06-12 19:52:14 -05002820 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002821 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002822 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002823 return 0;
2824 break;
2825 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002826 /* NULL username means anonymous session */
2827 if (ses->user_name == NULL) {
2828 if (!vol->nullauth)
2829 return 0;
2830 break;
2831 }
2832
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002833 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002834 if (strncmp(ses->user_name,
2835 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002836 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002837 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002838 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002839 ses->password != NULL &&
2840 strncmp(ses->password,
2841 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002842 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002843 return 0;
2844 }
2845 return 1;
2846}
2847
Aurelien Aptelb327a712018-01-24 13:46:10 +01002848/**
2849 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2850 *
2851 * A new IPC connection is made and stored in the session
2852 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2853 */
2854static int
2855cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2856{
2857 int rc = 0, xid;
2858 struct cifs_tcon *tcon;
2859 struct nls_table *nls_codepage;
2860 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2861 bool seal = false;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002862 struct TCP_Server_Info *server = ses->server;
Aurelien Aptelb327a712018-01-24 13:46:10 +01002863
2864 /*
2865 * If the mount request that resulted in the creation of the
2866 * session requires encryption, force IPC to be encrypted too.
2867 */
2868 if (volume_info->seal) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002869 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
Aurelien Aptelb327a712018-01-24 13:46:10 +01002870 seal = true;
2871 else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002872 cifs_server_dbg(VFS,
Aurelien Aptelb327a712018-01-24 13:46:10 +01002873 "IPC: server doesn't support encryption\n");
2874 return -EOPNOTSUPP;
2875 }
2876 }
2877
2878 tcon = tconInfoAlloc();
2879 if (tcon == NULL)
2880 return -ENOMEM;
2881
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002882 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002883
2884 /* cannot fail */
2885 nls_codepage = load_nls_default();
2886
2887 xid = get_xid();
2888 tcon->ses = ses;
2889 tcon->ipc = true;
2890 tcon->seal = seal;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002891 rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002892 free_xid(xid);
2893
2894 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002895 cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002896 tconInfoFree(tcon);
2897 goto out;
2898 }
2899
2900 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2901
2902 ses->tcon_ipc = tcon;
2903out:
2904 unload_nls(nls_codepage);
2905 return rc;
2906}
2907
2908/**
2909 * cifs_free_ipc - helper to release the session IPC tcon
2910 *
2911 * Needs to be called everytime a session is destroyed
2912 */
2913static int
2914cifs_free_ipc(struct cifs_ses *ses)
2915{
2916 int rc = 0, xid;
2917 struct cifs_tcon *tcon = ses->tcon_ipc;
2918
2919 if (tcon == NULL)
2920 return 0;
2921
2922 if (ses->server->ops->tree_disconnect) {
2923 xid = get_xid();
2924 rc = ses->server->ops->tree_disconnect(xid, tcon);
2925 free_xid(xid);
2926 }
2927
2928 if (rc)
2929 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
2930
2931 tconInfoFree(tcon);
2932 ses->tcon_ipc = NULL;
2933 return rc;
2934}
2935
Steve French96daf2b2011-05-27 04:34:02 +00002936static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002937cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938{
Steve French96daf2b2011-05-27 04:34:02 +00002939 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302941 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002942 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002943 if (ses->status == CifsExiting)
2944 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002945 if (!match_session(ses, vol))
2946 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002947 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302948 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002949 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302951 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 return NULL;
2953}
2954
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03002955void cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002956{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002957 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002958 struct TCP_Server_Info *server = ses->server;
2959
Joe Perchesf96637b2013-05-04 22:12:25 -05002960 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002961
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302962 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002963 if (ses->status == CifsExiting) {
2964 spin_unlock(&cifs_tcp_ses_lock);
2965 return;
2966 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002967 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302968 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002969 return;
2970 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002971 if (ses->status == CifsGood)
2972 ses->status = CifsExiting;
2973 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002974
Aurelien Aptelb327a712018-01-24 13:46:10 +01002975 cifs_free_ipc(ses);
2976
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002977 if (ses->status == CifsExiting && server->ops->logoff) {
2978 xid = get_xid();
2979 rc = server->ops->logoff(xid, ses);
2980 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002981 cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002982 __func__, rc);
2983 _free_xid(xid);
2984 }
2985
2986 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002987 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302988 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002989
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02002990 /* close any extra channels */
2991 if (ses->chan_count > 1) {
2992 int i;
2993
2994 for (i = 1; i < ses->chan_count; i++)
2995 cifs_put_tcp_session(ses->chans[i].server, 0);
2996 }
2997
Jeff Layton14fbf502008-11-14 13:53:46 -05002998 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002999 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05003000}
3001
Jeff Layton8a8798a2012-01-17 16:09:15 -05003002#ifdef CONFIG_KEYS
3003
Chen Gang057d6332013-07-19 09:01:36 +08003004/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
3005#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05003006
3007/* Populate username and pw fields from keyring if possible */
3008static int
3009cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
3010{
3011 int rc = 0;
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003012 int is_domain = 0;
David Howells146aa8b2015-10-21 14:04:48 +01003013 const char *delim, *payload;
3014 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003015 ssize_t len;
3016 struct key *key;
3017 struct TCP_Server_Info *server = ses->server;
3018 struct sockaddr_in *sa;
3019 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01003020 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003021
3022 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
3023 if (!desc)
3024 return -ENOMEM;
3025
3026 /* try to find an address key first */
3027 switch (server->dstaddr.ss_family) {
3028 case AF_INET:
3029 sa = (struct sockaddr_in *)&server->dstaddr;
3030 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
3031 break;
3032 case AF_INET6:
3033 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
3034 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
3035 break;
3036 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05003037 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
3038 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003039 rc = -EINVAL;
3040 goto out_err;
3041 }
3042
Joe Perchesf96637b2013-05-04 22:12:25 -05003043 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003044 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003045 if (IS_ERR(key)) {
3046 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003047 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003048 rc = PTR_ERR(key);
3049 goto out_err;
3050 }
3051
3052 /* didn't work, try to find a domain key */
3053 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05003054 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003055 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003056 if (IS_ERR(key)) {
3057 rc = PTR_ERR(key);
3058 goto out_err;
3059 }
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003060 is_domain = 1;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003061 }
3062
3063 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00003064 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003065 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05003066 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003067 goto out_key_put;
3068 }
3069
3070 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01003071 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003072 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05003073 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003074 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003075 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
3076 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003077 rc = -EINVAL;
3078 goto out_key_put;
3079 }
3080
3081 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003082 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003083 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
3084 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003085 rc = -EINVAL;
3086 goto out_key_put;
3087 }
3088
3089 vol->username = kstrndup(payload, len, GFP_KERNEL);
3090 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003091 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
3092 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003093 rc = -ENOMEM;
3094 goto out_key_put;
3095 }
Joe Perchesf96637b2013-05-04 22:12:25 -05003096 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003097
3098 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003099 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003100 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003101 rc = -EINVAL;
3102 kfree(vol->username);
3103 vol->username = NULL;
3104 goto out_key_put;
3105 }
3106
3107 ++delim;
3108 vol->password = kstrndup(delim, len, GFP_KERNEL);
3109 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003110 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
3111 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003112 rc = -ENOMEM;
3113 kfree(vol->username);
3114 vol->username = NULL;
3115 goto out_key_put;
3116 }
3117
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003118 /*
3119 * If we have a domain key then we must set the domainName in the
3120 * for the request.
3121 */
3122 if (is_domain && ses->domainName) {
3123 vol->domainname = kstrndup(ses->domainName,
3124 strlen(ses->domainName),
3125 GFP_KERNEL);
3126 if (!vol->domainname) {
Joe Perchesa0a30362020-04-14 22:42:53 -07003127 cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
3128 len);
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003129 rc = -ENOMEM;
3130 kfree(vol->username);
3131 vol->username = NULL;
Waiman Long453431a2020-08-06 23:18:13 -07003132 kfree_sensitive(vol->password);
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003133 vol->password = NULL;
3134 goto out_key_put;
3135 }
3136 }
3137
Jeff Layton8a8798a2012-01-17 16:09:15 -05003138out_key_put:
3139 up_read(&key->sem);
3140 key_put(key);
3141out_err:
3142 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05003143 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003144 return rc;
3145}
3146#else /* ! CONFIG_KEYS */
3147static inline int
3148cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
3149 struct cifs_ses *ses __attribute__((unused)))
3150{
3151 return -ENOSYS;
3152}
3153#endif /* CONFIG_KEYS */
3154
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003155/**
3156 * cifs_get_smb_ses - get a session matching @volume_info data from @server
3157 *
3158 * This function assumes it is being called from cifs_mount() where we
3159 * already got a server reference (server refcount +1). See
3160 * cifs_get_tcon() for refcount explanations.
3161 */
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003162struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04003163cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3164{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003165 int rc = -ENOMEM;
3166 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003167 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003168 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3169 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04003170
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003171 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04003172
Jeff Layton4ff67b72010-07-06 20:43:02 -04003173 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04003174 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003175 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3176 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04003177
Jeff Layton36988c72010-04-24 07:57:43 -04003178 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003179 rc = cifs_negotiate_protocol(xid, ses);
3180 if (rc) {
3181 mutex_unlock(&ses->session_mutex);
3182 /* problem -- put our ses reference */
3183 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003184 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003185 return ERR_PTR(rc);
3186 }
Jeff Layton36988c72010-04-24 07:57:43 -04003187 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003188 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003189 rc = cifs_setup_session(xid, ses,
3190 volume_info->local_nls);
3191 if (rc) {
3192 mutex_unlock(&ses->session_mutex);
3193 /* problem -- put our reference */
3194 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003195 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003196 return ERR_PTR(rc);
3197 }
3198 }
3199 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003200
3201 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003202 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003203 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003204 return ses;
3205 }
3206
Joe Perchesf96637b2013-05-04 22:12:25 -05003207 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003208 ses = sesInfoAlloc();
3209 if (ses == NULL)
3210 goto get_ses_fail;
3211
3212 /* new SMB session uses our server ref */
3213 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003214 if (server->dstaddr.ss_family == AF_INET6)
3215 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003216 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003217 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003218
Steve French8727c8a2011-02-25 01:11:56 -06003219 if (volume_info->username) {
3220 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3221 if (!ses->user_name)
3222 goto get_ses_fail;
3223 }
Jeff Layton36988c72010-04-24 07:57:43 -04003224
3225 /* volume_info->password freed at unmount */
3226 if (volume_info->password) {
3227 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3228 if (!ses->password)
3229 goto get_ses_fail;
3230 }
3231 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003232 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3233 if (!ses->domainName)
3234 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003235 }
Germano Percossi39566442016-12-15 12:31:18 +05303236 if (volume_info->domainauto)
3237 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003238 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003239 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003240
Jeff Layton28e11bd2013-05-26 07:01:00 -04003241 ses->sectype = volume_info->sectype;
3242 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003243 mutex_lock(&ses->session_mutex);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003244
3245 /* add server as first channel */
3246 ses->chans[0].server = server;
3247 ses->chan_count = 1;
3248 ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1;
3249
Jeff Layton198b5682010-04-24 07:57:48 -04003250 rc = cifs_negotiate_protocol(xid, ses);
3251 if (!rc)
3252 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003253
3254 /* each channel uses a different signing key */
3255 memcpy(ses->chans[0].signkey, ses->smb3signingkey,
3256 sizeof(ses->smb3signingkey));
3257
Jeff Layton36988c72010-04-24 07:57:43 -04003258 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003259 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003260 goto get_ses_fail;
3261
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003262 /* success, put it on the list and add it as first channel */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303263 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003264 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303265 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003266
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003267 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003268
3269 cifs_setup_ipc(ses, volume_info);
3270
Jeff Layton36988c72010-04-24 07:57:43 -04003271 return ses;
3272
3273get_ses_fail:
3274 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003275 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003276 return ERR_PTR(rc);
3277}
3278
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003279static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003280{
3281 if (tcon->tidStatus == CifsExiting)
3282 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003283 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003284 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003285 if (tcon->seal != volume_info->seal)
3286 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003287 if (tcon->snapshot_time != volume_info->snapshot_time)
3288 return 0;
Steve Frenchca567eb2019-03-29 16:31:07 -05003289 if (tcon->handle_timeout != volume_info->handle_timeout)
3290 return 0;
Steve French3e7a02d2019-09-11 21:46:20 -05003291 if (tcon->no_lease != volume_info->no_lease)
3292 return 0;
Steve French82e93672020-05-19 03:06:57 -05003293 if (tcon->nodelete != volume_info->nodelete)
3294 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003295 return 1;
3296}
3297
Steve French96daf2b2011-05-27 04:34:02 +00003298static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003299cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300{
3301 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003302 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303304 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003305 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003306 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Paulo Alcantara65303de2020-04-20 19:42:57 -03003307#ifdef CONFIG_CIFS_DFS_UPCALL
3308 if (tcon->dfs_path)
3309 continue;
3310#endif
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003311 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003312 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003313 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303314 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315 return tcon;
3316 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303317 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318 return NULL;
3319}
3320
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003321void
Steve French96daf2b2011-05-27 04:34:02 +00003322cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003323{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003324 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003325 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003326
Aurelien Aptelb327a712018-01-24 13:46:10 +01003327 /*
3328 * IPC tcon share the lifetime of their session and are
3329 * destroyed in the session put function
3330 */
3331 if (tcon == NULL || tcon->ipc)
3332 return;
3333
3334 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003335 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303336 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003337 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303338 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003339 return;
3340 }
3341
3342 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303343 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003344
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003345 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003346 if (ses->server->ops->tree_disconnect)
3347 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003348 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003349
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303350 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003351 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003352 cifs_put_smb_ses(ses);
3353}
3354
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003355/**
3356 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3357 *
3358 * - tcon refcount is the number of mount points using the tcon.
3359 * - ses refcount is the number of tcon using the session.
3360 *
3361 * 1. This function assumes it is being called from cifs_mount() where
3362 * we already got a session reference (ses refcount +1).
3363 *
3364 * 2. Since we're in the context of adding a mount point, the end
3365 * result should be either:
3366 *
3367 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3368 * its session refcount incremented (1 new tcon). This +1 was
3369 * already done in (1).
3370 *
3371 * b) an existing tcon with refcount+1 (add a mount point to it) and
3372 * identical ses refcount (no new tcon). Because of (1) we need to
3373 * decrement the ses refcount.
3374 */
Steve French96daf2b2011-05-27 04:34:02 +00003375static struct cifs_tcon *
3376cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003377{
3378 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003379 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003380
Steve French8b217fe2016-11-11 22:36:20 -06003381 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003382 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003383 /*
3384 * tcon has refcount already incremented but we need to
3385 * decrement extra ses reference gotten by caller (case b)
3386 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003387 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003388 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003389 return tcon;
3390 }
3391
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003392 if (!ses->server->ops->tree_connect) {
3393 rc = -ENOSYS;
3394 goto out_fail;
3395 }
3396
Jeff Laytond00c28d2010-04-24 07:57:44 -04003397 tcon = tconInfoAlloc();
3398 if (tcon == NULL) {
3399 rc = -ENOMEM;
3400 goto out_fail;
3401 }
3402
Steve French8b217fe2016-11-11 22:36:20 -06003403 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003404 if (ses->server->vals->protocol_id == 0) {
3405 cifs_dbg(VFS,
3406 "Use SMB2 or later for snapshot mount option\n");
3407 rc = -EOPNOTSUPP;
3408 goto out_fail;
3409 } else
3410 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003411 }
3412
Steve Frenchca567eb2019-03-29 16:31:07 -05003413 if (volume_info->handle_timeout) {
3414 if (ses->server->vals->protocol_id == 0) {
3415 cifs_dbg(VFS,
3416 "Use SMB2.1 or later for handle timeout option\n");
3417 rc = -EOPNOTSUPP;
3418 goto out_fail;
3419 } else
3420 tcon->handle_timeout = volume_info->handle_timeout;
3421 }
3422
Jeff Laytond00c28d2010-04-24 07:57:44 -04003423 tcon->ses = ses;
3424 if (volume_info->password) {
3425 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3426 if (!tcon->password) {
3427 rc = -ENOMEM;
3428 goto out_fail;
3429 }
3430 }
3431
Steve French23657ad2018-04-22 15:14:58 -05003432 if (volume_info->seal) {
3433 if (ses->server->vals->protocol_id == 0) {
3434 cifs_dbg(VFS,
3435 "SMB3 or later required for encryption\n");
3436 rc = -EOPNOTSUPP;
3437 goto out_fail;
3438 } else if (tcon->ses->server->capabilities &
3439 SMB2_GLOBAL_CAP_ENCRYPTION)
3440 tcon->seal = true;
3441 else {
3442 cifs_dbg(VFS, "Encryption is not supported on share\n");
3443 rc = -EOPNOTSUPP;
3444 goto out_fail;
3445 }
3446 }
3447
Steve French8505c8b2018-06-18 14:01:59 -05003448 if (volume_info->linux_ext) {
3449 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003450 tcon->posix_extensions = true;
Joe Perchesa0a30362020-04-14 22:42:53 -07003451 pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003452 } else {
Joe Perchesa0a30362020-04-14 22:42:53 -07003453 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
Steve French8505c8b2018-06-18 14:01:59 -05003454 rc = -EOPNOTSUPP;
3455 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003456 }
Steve Frenchb3266142018-05-20 23:41:10 -05003457 }
Steve Frenchb3266142018-05-20 23:41:10 -05003458
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003459 /*
3460 * BB Do we need to wrap session_mutex around this TCon call and Unix
3461 * SetFS as we do on SessSetup and reconnect?
3462 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003463 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003464 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3465 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003466 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003467 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003468 if (rc)
3469 goto out_fail;
3470
Steve Frenchb618f002015-11-03 09:15:03 -06003471 tcon->use_persistent = false;
3472 /* check if SMB2 or later, CIFS does not support persistent handles */
3473 if (volume_info->persistent) {
3474 if (ses->server->vals->protocol_id == 0) {
3475 cifs_dbg(VFS,
3476 "SMB3 or later required for persistent handles\n");
3477 rc = -EOPNOTSUPP;
3478 goto out_fail;
3479 } else if (ses->server->capabilities &
3480 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3481 tcon->use_persistent = true;
3482 else /* persistent handles requested but not supported */ {
3483 cifs_dbg(VFS,
3484 "Persistent handles not supported on share\n");
3485 rc = -EOPNOTSUPP;
3486 goto out_fail;
3487 }
3488 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3489 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3490 && (volume_info->nopersistent == false)) {
3491 cifs_dbg(FYI, "enabling persistent handles\n");
3492 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003493 } else if (volume_info->resilient) {
3494 if (ses->server->vals->protocol_id == 0) {
3495 cifs_dbg(VFS,
3496 "SMB2.1 or later required for resilient handles\n");
3497 rc = -EOPNOTSUPP;
3498 goto out_fail;
3499 }
3500 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003501 }
3502
Steve Frenchcae53f72019-09-03 17:49:46 -05003503 /* If the user really knows what they are doing they can override */
3504 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3505 if (volume_info->cache_ro)
3506 cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3507 else if (volume_info->cache_rw)
3508 cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3509 }
3510
Kenneth D'souza8fd6e1d2020-05-18 13:01:34 +05303511 if (volume_info->no_lease) {
3512 if (ses->server->vals->protocol_id == 0) {
3513 cifs_dbg(VFS,
3514 "SMB2 or later required for nolease option\n");
3515 rc = -EOPNOTSUPP;
3516 goto out_fail;
3517 } else
3518 tcon->no_lease = volume_info->no_lease;
3519 }
3520
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003521 /*
3522 * We can have only one retry value for a connection to a share so for
3523 * resources mounted more than once to the same server share the last
3524 * value passed in for the retry flag is used.
3525 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003526 tcon->retry = volume_info->retry;
3527 tcon->nocase = volume_info->nocase;
Steve French3c6e65e2020-10-21 00:15:42 -05003528 if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
3529 tcon->nohandlecache = volume_info->nohandlecache;
3530 else
3531 tcon->nohandlecache = 1;
Steve French82e93672020-05-19 03:06:57 -05003532 tcon->nodelete = volume_info->nodelete;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003533 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003534 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003535
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303536 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003537 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303538 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003539
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303540 cifs_fscache_get_super_cookie(tcon);
3541
Jeff Laytond00c28d2010-04-24 07:57:44 -04003542 return tcon;
3543
3544out_fail:
3545 tconInfoFree(tcon);
3546 return ERR_PTR(rc);
3547}
3548
Jeff Layton9d002df2010-10-06 19:51:11 -04003549void
3550cifs_put_tlink(struct tcon_link *tlink)
3551{
3552 if (!tlink || IS_ERR(tlink))
3553 return;
3554
3555 if (!atomic_dec_and_test(&tlink->tl_count) ||
3556 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3557 tlink->tl_time = jiffies;
3558 return;
3559 }
3560
3561 if (!IS_ERR(tlink_tcon(tlink)))
3562 cifs_put_tcon(tlink_tcon(tlink));
3563 kfree(tlink);
3564 return;
3565}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003566
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003567static int
3568compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3569{
3570 struct cifs_sb_info *old = CIFS_SB(sb);
3571 struct cifs_sb_info *new = mnt_data->cifs_sb;
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003572 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3573 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003574
3575 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3576 return 0;
3577
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003578 if (old->mnt_cifs_serverino_autodisabled)
3579 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3580
3581 if (oldflags != newflags)
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003582 return 0;
3583
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003584 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003585 * We want to share sb only if we don't specify an r/wsize or
3586 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003587 */
3588 if (new->wsize && new->wsize < old->wsize)
3589 return 0;
3590
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003591 if (new->rsize && new->rsize < old->rsize)
3592 return 0;
3593
Eric W. Biederman1f682332013-02-06 01:20:20 -08003594 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003595 return 0;
3596
3597 if (old->mnt_file_mode != new->mnt_file_mode ||
3598 old->mnt_dir_mode != new->mnt_dir_mode)
3599 return 0;
3600
3601 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3602 return 0;
3603
3604 if (old->actimeo != new->actimeo)
3605 return 0;
3606
3607 return 1;
3608}
3609
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003610static int
3611match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3612{
3613 struct cifs_sb_info *old = CIFS_SB(sb);
3614 struct cifs_sb_info *new = mnt_data->cifs_sb;
Ronnie Sahlbergfe129262020-01-22 11:07:56 +10003615 bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3616 old->prepath;
3617 bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3618 new->prepath;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003619
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003620 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003621 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003622 else if (!old_set && !new_set)
3623 return 1;
3624
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003625 return 0;
3626}
3627
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003628int
3629cifs_match_super(struct super_block *sb, void *data)
3630{
3631 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3632 struct smb_vol *volume_info;
3633 struct cifs_sb_info *cifs_sb;
3634 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003635 struct cifs_ses *ses;
3636 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003637 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003638 int rc = 0;
3639
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003640 spin_lock(&cifs_tcp_ses_lock);
3641 cifs_sb = CIFS_SB(sb);
3642 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3643 if (IS_ERR(tlink)) {
3644 spin_unlock(&cifs_tcp_ses_lock);
3645 return rc;
3646 }
3647 tcon = tlink_tcon(tlink);
3648 ses = tcon->ses;
3649 tcp_srv = ses->server;
3650
3651 volume_info = mnt_data->vol;
3652
Jeff Layton9fa114f2012-11-26 11:09:57 -05003653 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003654 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003655 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003656 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003657 rc = 0;
3658 goto out;
3659 }
3660
3661 rc = compare_mount_options(sb, mnt_data);
3662out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003663 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003664 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003665 return rc;
3666}
3667
Jeff Layton09e50d52008-07-23 10:11:19 -04003668#ifdef CONFIG_DEBUG_LOCK_ALLOC
3669static struct lock_class_key cifs_key[2];
3670static struct lock_class_key cifs_slock_key[2];
3671
3672static inline void
3673cifs_reclassify_socket4(struct socket *sock)
3674{
3675 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003676 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003677 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3678 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3679}
3680
3681static inline void
3682cifs_reclassify_socket6(struct socket *sock)
3683{
3684 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003685 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003686 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3687 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3688}
3689#else
3690static inline void
3691cifs_reclassify_socket4(struct socket *sock)
3692{
3693}
3694
3695static inline void
3696cifs_reclassify_socket6(struct socket *sock)
3697{
3698}
3699#endif
3700
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003702static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703{
Steve French50c2f752007-07-13 00:33:32 +00003704 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705
Steve French50c2f752007-07-13 00:33:32 +00003706 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 /* mask a nibble at a time and encode */
3708 target[j] = 'A' + (0x0F & (source[i] >> 4));
3709 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003710 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 }
3712
3713}
3714
Ben Greear3eb9a882010-09-01 17:06:02 -07003715static int
3716bind_socket(struct TCP_Server_Info *server)
3717{
3718 int rc = 0;
3719 if (server->srcaddr.ss_family != AF_UNSPEC) {
3720 /* Bind to the specified local IP address */
3721 struct socket *socket = server->ssocket;
3722 rc = socket->ops->bind(socket,
3723 (struct sockaddr *) &server->srcaddr,
3724 sizeof(server->srcaddr));
3725 if (rc < 0) {
3726 struct sockaddr_in *saddr4;
3727 struct sockaddr_in6 *saddr6;
3728 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3729 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3730 if (saddr6->sin6_family == AF_INET6)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003731 cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003732 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003733 else
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003734 cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003735 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003736 }
3737 }
3738 return rc;
3739}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
3741static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003742ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743{
3744 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003745 /*
3746 * some servers require RFC1001 sessinit before sending
3747 * negprot - BB check reconnection in case where second
3748 * sessinit is sent but no second negprot
3749 */
3750 struct rfc1002_session_packet *ses_init_buf;
3751 struct smb_hdr *smb_buf;
3752 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3753 GFP_KERNEL);
3754 if (ses_init_buf) {
3755 ses_init_buf->trailer.session_req.called_len = 32;
3756
Colin Ian King997152f2016-01-25 16:25:54 +00003757 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003758 rfc1002mangle(ses_init_buf->trailer.
3759 session_req.called_name,
3760 server->server_RFC1001_name,
3761 RFC1001_NAME_LEN_WITH_NULL);
3762 else
3763 rfc1002mangle(ses_init_buf->trailer.
3764 session_req.called_name,
3765 DEFAULT_CIFS_CALLED_NAME,
3766 RFC1001_NAME_LEN_WITH_NULL);
3767
3768 ses_init_buf->trailer.session_req.calling_len = 32;
3769
3770 /*
3771 * calling name ends in null (byte 16) from old smb
3772 * convention.
3773 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003774 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003775 rfc1002mangle(ses_init_buf->trailer.
3776 session_req.calling_name,
3777 server->workstation_RFC1001_name,
3778 RFC1001_NAME_LEN_WITH_NULL);
3779 else
3780 rfc1002mangle(ses_init_buf->trailer.
3781 session_req.calling_name,
3782 "LINUX_CIFS_CLNT",
3783 RFC1001_NAME_LEN_WITH_NULL);
3784
3785 ses_init_buf->trailer.session_req.scope1 = 0;
3786 ses_init_buf->trailer.session_req.scope2 = 0;
3787 smb_buf = (struct smb_hdr *)ses_init_buf;
3788
3789 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003790 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003791 rc = smb_send(server, smb_buf, 0x44);
3792 kfree(ses_init_buf);
3793 /*
3794 * RFC1001 layer in at least one server
3795 * requires very short break before negprot
3796 * presumably because not expecting negprot
3797 * to follow so fast. This is a simple
3798 * solution that works without
3799 * complicating the code and causes no
3800 * significant slowing down on mount
3801 * for everyone else
3802 */
3803 usleep_range(1000, 2000);
3804 }
3805 /*
3806 * else the negprot may still work without this
3807 * even though malloc failed
3808 */
3809
3810 return rc;
3811}
3812
3813static int
3814generic_ip_connect(struct TCP_Server_Info *server)
3815{
3816 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003817 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003818 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003819 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003820 struct sockaddr *saddr;
3821
3822 saddr = (struct sockaddr *) &server->dstaddr;
3823
3824 if (server->dstaddr.ss_family == AF_INET6) {
Samuel Cabrerodef6e1d2020-10-16 11:54:55 +02003825 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr;
3826
3827 sport = ipv6->sin6_port;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003828 slen = sizeof(struct sockaddr_in6);
3829 sfamily = AF_INET6;
Samuel Cabrerodef6e1d2020-10-16 11:54:55 +02003830 cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr,
3831 ntohs(sport));
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003832 } else {
Samuel Cabrerodef6e1d2020-10-16 11:54:55 +02003833 struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr;
3834
3835 sport = ipv4->sin_port;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003836 slen = sizeof(struct sockaddr_in);
3837 sfamily = AF_INET;
Samuel Cabrerodef6e1d2020-10-16 11:54:55 +02003838 cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr,
3839 ntohs(sport));
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003842 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003843 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3844 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 if (rc < 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003846 cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003847 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003850
3851 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003852 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003853 server->ssocket = socket;
3854 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003855 if (sfamily == AF_INET6)
3856 cifs_reclassify_socket6(socket);
3857 else
3858 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 }
3860
Ben Greear3eb9a882010-09-01 17:06:02 -07003861 rc = bind_socket(server);
3862 if (rc < 0)
3863 return rc;
3864
Jeff Laytond5c56052008-12-01 18:42:33 -05003865 /*
3866 * Eventually check for other socket options to change from
3867 * the default. sock_setsockopt not used because it expects
3868 * user space buffer
3869 */
3870 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003871 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003872
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003873 /* make the bufsizes depend on wsize/rsize and max requests */
3874 if (server->noautotune) {
3875 if (socket->sk->sk_sndbuf < (200 * 1024))
3876 socket->sk->sk_sndbuf = 200 * 1024;
3877 if (socket->sk->sk_rcvbuf < (140 * 1024))
3878 socket->sk->sk_rcvbuf = 140 * 1024;
3879 }
3880
Christoph Hellwig12abc5e2020-05-28 07:12:19 +02003881 if (server->tcp_nodelay)
3882 tcp_sock_set_nodelay(socket->sk);
Steve French6a5fa2362010-01-01 01:28:43 +00003883
Joe Perchesf96637b2013-05-04 22:12:25 -05003884 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003885 socket->sk->sk_sndbuf,
3886 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3887
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003888 rc = socket->ops->connect(socket, saddr, slen,
3889 server->noblockcnt ? O_NONBLOCK : 0);
Paulo Alcantara (SUSE)d532cc72019-10-10 12:31:58 -03003890 /*
3891 * When mounting SMB root file systems, we do not want to block in
3892 * connect. Otherwise bail out and then let cifs_reconnect() perform
3893 * reconnect failover - if possible.
3894 */
3895 if (server->noblockcnt && rc == -EINPROGRESS)
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003896 rc = 0;
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003897 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003898 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003899 sock_release(socket);
3900 server->ssocket = NULL;
3901 return rc;
3902 }
3903
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003904 if (sport == htons(RFC1001_PORT))
3905 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003906
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 return rc;
3908}
3909
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003910static int
3911ip_connect(struct TCP_Server_Info *server)
3912{
Steve French6da97912011-03-13 18:55:55 +00003913 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003914 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3915 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3916
3917 if (server->dstaddr.ss_family == AF_INET6)
3918 sport = &addr6->sin6_port;
3919 else
3920 sport = &addr->sin_port;
3921
3922 if (*sport == 0) {
3923 int rc;
3924
3925 /* try with 445 port at first */
3926 *sport = htons(CIFS_PORT);
3927
3928 rc = generic_ip_connect(server);
3929 if (rc >= 0)
3930 return rc;
3931
3932 /* if it failed, try with 139 port */
3933 *sport = htons(RFC1001_PORT);
3934 }
3935
3936 return generic_ip_connect(server);
3937}
3938
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003939void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003940 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003941{
3942 /* if we are reconnecting then should we check to see if
3943 * any requested capabilities changed locally e.g. via
3944 * remount but we can not do much about it here
3945 * if they have (even if we could detect it by the following)
3946 * Perhaps we could add a backpointer to array of sb from tcon
3947 * or if we change to make all sb to same share the same
3948 * sb as NFS - then we only have one backpointer to sb.
3949 * What if we wanted to mount the server share twice once with
3950 * and once without posixacls or posix paths? */
3951 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003952
Steve Frenchc18c8422007-07-18 23:21:09 +00003953 if (vol_info && vol_info->no_linux_ext) {
3954 tcon->fsUnixInfo.Capability = 0;
3955 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003956 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003957 return;
3958 } else if (vol_info)
3959 tcon->unix_ext = 1; /* Unix Extensions supported */
3960
3961 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003962 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003963 return;
3964 }
Steve French50c2f752007-07-13 00:33:32 +00003965
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003966 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003967 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003968 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003969 /* check for reconnect case in which we do not
3970 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003971 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003972 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003973 originally at mount time */
3974 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3975 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003976 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3977 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003978 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003979 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003980 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003981 cifs_dbg(VFS, "possible reconnect error\n");
3982 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003983 }
Steve French8af18972007-02-14 04:42:51 +00003984 }
Steve French50c2f752007-07-13 00:33:32 +00003985
Steve French6848b732011-05-26 18:38:54 +00003986 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003987 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003988
Steve French8af18972007-02-14 04:42:51 +00003989 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003990 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003991 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003992 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003993 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003994 if (cifs_sb)
3995 cifs_sb->mnt_cifs_flags |=
3996 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003997 }
3998
Steve French75865f8c2007-06-24 18:30:48 +00003999 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00004000 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004001 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004002 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004003 if (cifs_sb)
4004 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00004005 CIFS_MOUNT_POSIX_PATHS;
4006 }
Steve French50c2f752007-07-13 00:33:32 +00004007
Joe Perchesf96637b2013-05-04 22:12:25 -05004008 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00004009#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00004010 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004011 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004012 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004013 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004014 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004015 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004016 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004017 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004018 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004019 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004020 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004021 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004022 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004023 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00004024 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004025 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00004026 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004027 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00004028#endif /* CIFS_DEBUG2 */
4029 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00004030 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004031 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00004032 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05004033 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 +00004034
Steve French8af18972007-02-14 04:42:51 +00004035 }
4036 }
4037}
4038
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004039int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004040 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004041{
Jeff Layton2de970f2010-10-06 19:51:12 -04004042 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
4043
Al Viro2ced6f62011-06-17 09:20:04 -04004044 spin_lock_init(&cifs_sb->tlink_tree_lock);
4045 cifs_sb->tlink_tree = RB_ROOT;
4046
Steve Frenche8506d22019-02-28 21:32:15 -06004047 cifs_sb->bsize = pvolume_info->bsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004048 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004049 * Temporarily set r/wsize for matching superblock. If we end up using
4050 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004051 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004052 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004053 cifs_sb->wsize = pvolume_info->wsize;
4054
Steve French3b795212008-11-13 19:45:32 +00004055 cifs_sb->mnt_uid = pvolume_info->linux_uid;
4056 cifs_sb->mnt_gid = pvolume_info->linux_gid;
4057 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
4058 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Frank Sorensonf52aa792020-02-12 15:31:48 -06004059 cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05004060 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00004061
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304062 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004063 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304064
Aurelien Aptel83930722018-09-20 18:10:25 -07004065 if (pvolume_info->nodfs)
4066 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00004067 if (pvolume_info->noperm)
4068 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4069 if (pvolume_info->setuids)
4070 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05004071 if (pvolume_info->setuidfromacl)
4072 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00004073 if (pvolume_info->server_ino)
4074 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4075 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05004076 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
4077 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00004078 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4079 if (pvolume_info->no_xattr)
4080 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4081 if (pvolume_info->sfu_emul)
4082 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4083 if (pvolume_info->nobrl)
4084 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05004085 if (pvolume_info->nohandlecache)
4086 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00004087 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00004088 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00004089 if (pvolume_info->mand_lock)
4090 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00004091 if (pvolume_info->rwpidforward)
4092 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French412094a2019-06-24 02:01:42 -05004093 if (pvolume_info->mode_ace)
4094 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
Steve French3b795212008-11-13 19:45:32 +00004095 if (pvolume_info->cifs_acl)
4096 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004097 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004098 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004099 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
4100 }
4101 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004102 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004103 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
4104 }
Steve French3b795212008-11-13 19:45:32 +00004105 if (pvolume_info->override_uid)
4106 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
4107 if (pvolume_info->override_gid)
4108 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
4109 if (pvolume_info->dynperm)
4110 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05304111 if (pvolume_info->fsc)
4112 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04004113 if (pvolume_info->multiuser)
4114 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
4115 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05004116 if (pvolume_info->strict_io)
4117 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00004118 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004119 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00004120 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
4121 }
Steve French83bbfa72019-08-27 23:58:54 -05004122 if (pvolume_info->cache_ro) {
4123 cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4124 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
Steve French41e033f2019-08-30 02:12:41 -05004125 } else if (pvolume_info->cache_rw) {
4126 cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4127 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4128 CIFS_MOUNT_RW_CACHE);
Steve French83bbfa72019-08-27 23:58:54 -05004129 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004130 if (pvolume_info->mfsymlinks) {
4131 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05004132 /*
4133 * Our SFU ("Services for Unix" emulation does not allow
4134 * creating symlinks but does allow reading existing SFU
4135 * symlinks (it does allow both creating and reading SFU
4136 * style mknod and FIFOs though). When "mfsymlinks" and
4137 * "sfu" are both enabled at the same time, it allows
4138 * reading both types of symlinks, but will only create
4139 * them with mfsymlinks format. This allows better
4140 * Apple compatibility (probably better for Samba too)
4141 * while still recognizing old Windows style symlinks.
4142 */
4143 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004144 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05004145 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004146 }
Steve French3b795212008-11-13 19:45:32 +00004147
4148 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05004149 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004150
4151 if (pvolume_info->prepath) {
4152 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
4153 if (cifs_sb->prepath == NULL)
4154 return -ENOMEM;
4155 }
4156
4157 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004158}
4159
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004160void
4161cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004162{
Sean Finneyb9468452011-04-11 13:19:32 +00004163 kfree(volume_info->username);
Waiman Long453431a2020-08-06 23:18:13 -07004164 kfree_sensitive(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02004165 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00004166 kfree(volume_info->domainname);
4167 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004168 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004169}
4170
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004171void
4172cifs_cleanup_volume_info(struct smb_vol *volume_info)
4173{
4174 if (!volume_info)
4175 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004176 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004177 kfree(volume_info);
4178}
4179
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004180/* Release all succeed connections */
4181static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4182 unsigned int xid,
4183 struct TCP_Server_Info *server,
4184 struct cifs_ses *ses, struct cifs_tcon *tcon)
4185{
4186 int rc = 0;
4187
4188 if (tcon)
4189 cifs_put_tcon(tcon);
4190 else if (ses)
4191 cifs_put_smb_ses(ses);
4192 else if (server)
4193 cifs_put_tcp_session(server, 0);
4194 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4195 free_xid(xid);
4196}
4197
4198/* Get connections for tcp, ses and tcon */
4199static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4200 unsigned int *xid,
4201 struct TCP_Server_Info **nserver,
4202 struct cifs_ses **nses, struct cifs_tcon **ntcon)
4203{
4204 int rc = 0;
4205 struct TCP_Server_Info *server;
4206 struct cifs_ses *ses;
4207 struct cifs_tcon *tcon;
4208
4209 *nserver = NULL;
4210 *nses = NULL;
4211 *ntcon = NULL;
4212
4213 *xid = get_xid();
4214
4215 /* get a reference to a tcp session */
4216 server = cifs_get_tcp_session(vol);
4217 if (IS_ERR(server)) {
4218 rc = PTR_ERR(server);
4219 return rc;
4220 }
4221
4222 *nserver = server;
4223
4224 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
4225 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4226 else
4227 server->max_credits = vol->max_credits;
4228
4229 /* get a reference to a SMB session */
4230 ses = cifs_get_smb_ses(server, vol);
4231 if (IS_ERR(ses)) {
4232 rc = PTR_ERR(ses);
4233 return rc;
4234 }
4235
4236 *nses = ses;
4237
4238 if ((vol->persistent == true) && (!(ses->server->capabilities &
4239 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004240 cifs_server_dbg(VFS, "persistent handles not supported by server\n");
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004241 return -EOPNOTSUPP;
4242 }
4243
4244 /* search for existing tcon to this server share */
4245 tcon = cifs_get_tcon(ses, vol);
4246 if (IS_ERR(tcon)) {
4247 rc = PTR_ERR(tcon);
4248 return rc;
4249 }
4250
4251 *ntcon = tcon;
4252
4253 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4254 if (tcon->posix_extensions)
4255 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4256
4257 /* tell server which Unix caps we support */
4258 if (cap_unix(tcon->ses)) {
4259 /*
4260 * reset of caps checks mount to see if unix extensions disabled
4261 * for just this mount.
4262 */
4263 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4264 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4265 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4266 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4267 return -EACCES;
4268 } else
4269 tcon->unix_ext = 0; /* server does not support them */
4270
4271 /* do not care if a following call succeed - informational */
Steve French1981eba2019-08-29 22:33:38 -05004272 if (!tcon->pipe && server->ops->qfs_tcon) {
Amir Goldstein0f060932020-02-03 21:46:43 +02004273 server->ops->qfs_tcon(*xid, tcon, cifs_sb);
Steve French1981eba2019-08-29 22:33:38 -05004274 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4275 if (tcon->fsDevInfo.DeviceCharacteristics &
Steve French52870d52019-10-01 21:25:46 -05004276 cpu_to_le32(FILE_READ_ONLY_DEVICE))
Steve French1981eba2019-08-29 22:33:38 -05004277 cifs_dbg(VFS, "mounted to read only share\n");
Steve French41e033f2019-08-30 02:12:41 -05004278 else if ((cifs_sb->mnt_cifs_flags &
4279 CIFS_MOUNT_RW_CACHE) == 0)
Steve French1981eba2019-08-29 22:33:38 -05004280 cifs_dbg(VFS, "read only mount of RW share\n");
Steve French41e033f2019-08-30 02:12:41 -05004281 /* no need to log a RW mount of a typical RW share */
Steve French1981eba2019-08-29 22:33:38 -05004282 }
4283 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004284
4285 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4286 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4287
4288 return 0;
4289}
4290
4291static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4292 struct cifs_tcon *tcon)
4293{
4294 struct tcon_link *tlink;
4295
4296 /* hang the tcon off of the superblock */
4297 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4298 if (tlink == NULL)
4299 return -ENOMEM;
4300
4301 tlink->tl_uid = ses->linux_uid;
4302 tlink->tl_tcon = tcon;
4303 tlink->tl_time = jiffies;
4304 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4305 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4306
4307 cifs_sb->master_tlink = tlink;
4308 spin_lock(&cifs_sb->tlink_tree_lock);
4309 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4310 spin_unlock(&cifs_sb->tlink_tree_lock);
4311
4312 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4313 TLINK_IDLE_EXPIRE);
4314 return 0;
4315}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004316
Steve French2d6d5892009-04-09 00:36:44 +00004317#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004318/*
4319 * cifs_build_path_to_root returns full path to root when we do not have an
4320 * exiting connection (tcon)
4321 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004322static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004323build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004324 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004325{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004326 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004327 unsigned int pplen = useppath && vol->prepath ?
4328 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004329 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004330
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004331 if (unc_len > MAX_TREE_SIZE)
4332 return ERR_PTR(-EINVAL);
4333
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004334 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004335 if (full_path == NULL)
4336 return ERR_PTR(-ENOMEM);
4337
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004338 memcpy(full_path, vol->UNC, unc_len);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004339 pos = full_path + unc_len;
4340
4341 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004342 *pos = CIFS_DIR_SEP(cifs_sb);
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004343 memcpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004344 pos += pplen;
4345 }
4346
4347 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004348 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004349 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004350 return full_path;
4351}
Sean Finneydd613942011-04-11 13:19:30 +00004352
Paulo Alcantara1c780222018-11-14 16:24:03 -02004353/**
4354 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4355 *
Sean Finneydd613942011-04-11 13:19:30 +00004356 *
Sean Finney046462a2011-04-11 13:19:33 +00004357 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4358 * to a string containing updated options for the submount. Otherwise it
4359 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004360 *
4361 * Returns the rc from get_dfs_path to the caller, which can be used to
4362 * determine whether there were referrals.
4363 */
4364static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004365expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004366 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004367 char *ref_path)
Sean Finneydd613942011-04-11 13:19:30 +00004368{
4369 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004370 struct dfs_info3_param referral = {0};
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004371 char *full_path = NULL, *mdata = NULL;
Sean Finneydd613942011-04-11 13:19:30 +00004372
Aurelien Aptel83930722018-09-20 18:10:25 -07004373 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4374 return -EREMOTE;
4375
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004376 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004377 if (IS_ERR(full_path))
4378 return PTR_ERR(full_path);
4379
Paulo Alcantara1c780222018-11-14 16:24:03 -02004380 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4381 ref_path, &referral, NULL);
4382 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004383 char *fake_devname = NULL;
4384
4385 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004386 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004387 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004388 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004389
Sean Finneydd613942011-04-11 13:19:30 +00004390 if (IS_ERR(mdata)) {
4391 rc = PTR_ERR(mdata);
4392 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004393 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004394 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004395 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004396 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004397 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004398 kfree(fake_devname);
4399 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004400 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004401 }
4402 kfree(full_path);
4403 return rc;
4404}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004405
4406static inline int get_next_dfs_tgt(const char *path,
4407 struct dfs_cache_tgt_list *tgt_list,
4408 struct dfs_cache_tgt_iterator **tgt_it)
4409{
4410 if (!*tgt_it)
4411 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4412 else
4413 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4414 return !*tgt_it ? -EHOSTDOWN : 0;
4415}
4416
4417static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4418 struct smb_vol *fake_vol, struct smb_vol *vol)
4419{
4420 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4421 int len = strlen(tgt) + 2;
4422 char *new_unc;
4423
4424 new_unc = kmalloc(len, GFP_KERNEL);
4425 if (!new_unc)
4426 return -ENOMEM;
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +10004427 scnprintf(new_unc, len, "\\%s", tgt);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004428
4429 kfree(vol->UNC);
4430 vol->UNC = new_unc;
4431
4432 if (fake_vol->prepath) {
4433 kfree(vol->prepath);
4434 vol->prepath = fake_vol->prepath;
4435 fake_vol->prepath = NULL;
4436 }
4437 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4438
4439 return 0;
4440}
4441
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004442static int setup_dfs_tgt_conn(const char *path, const char *full_path,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004443 const struct dfs_cache_tgt_iterator *tgt_it,
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004444 struct cifs_sb_info *cifs_sb, struct smb_vol *vol, unsigned int *xid,
4445 struct TCP_Server_Info **server, struct cifs_ses **ses,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004446 struct cifs_tcon **tcon)
4447{
4448 int rc;
4449 struct dfs_info3_param ref = {0};
4450 char *mdata = NULL, *fake_devname = NULL;
Steve Frenchd0959b02019-10-05 10:53:58 -05004451 struct smb_vol fake_vol = {NULL};
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004452
4453 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4454
4455 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4456 if (rc)
4457 return rc;
4458
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004459 mdata = cifs_compose_mount_options(cifs_sb->mountdata, full_path + 1, &ref, &fake_devname);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004460 free_dfs_info_param(&ref);
4461
4462 if (IS_ERR(mdata)) {
4463 rc = PTR_ERR(mdata);
4464 mdata = NULL;
4465 } else {
4466 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4467 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4468 false);
4469 }
4470 kfree(mdata);
4471 kfree(fake_devname);
4472
4473 if (!rc) {
4474 /*
4475 * We use a 'fake_vol' here because we need pass it down to the
4476 * mount_{get,put} functions to test connection against new DFS
4477 * targets.
4478 */
4479 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4480 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4481 tcon);
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004482 if (!rc || (*server && *ses)) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004483 /*
4484 * We were able to connect to new target server.
4485 * Update current volume info with new target server.
4486 */
4487 rc = update_vol_info(tgt_it, &fake_vol, vol);
4488 }
4489 }
4490 cifs_cleanup_volume_info_contents(&fake_vol);
4491 return rc;
4492}
4493
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004494static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb,
4495 struct smb_vol *vol, struct cifs_ses *root_ses, unsigned int *xid,
4496 struct TCP_Server_Info **server, struct cifs_ses **ses,
4497 struct cifs_tcon **tcon)
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004498{
4499 int rc;
4500 struct dfs_cache_tgt_list tgt_list;
4501 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4502
4503 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4504 return -EOPNOTSUPP;
4505
4506 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4507 if (rc)
4508 return rc;
4509
4510 for (;;) {
4511 /* Get next DFS target server - if any */
4512 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4513 if (rc)
4514 break;
4515 /* Connect to next DFS target */
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004516 rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, vol, xid, server, ses,
4517 tcon);
4518 if (!rc || (*server && *ses))
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004519 break;
4520 }
4521 if (!rc) {
4522 /*
4523 * Update DFS target hint in DFS referral cache with the target
4524 * server we successfully reconnected to.
4525 */
4526 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4527 cifs_sb->local_nls,
4528 cifs_remap(cifs_sb), path,
4529 tgt_it);
4530 }
4531 dfs_cache_free_tgts(&tgt_list);
4532 return rc;
4533}
Steve French2d6d5892009-04-09 00:36:44 +00004534#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004535
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004536int
Jeff Layton04db79b2011-07-06 08:10:38 -04004537cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004538 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004540 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004541
Steve Frenchc7c137b2018-06-06 17:59:29 -05004542 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004543 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544
Jeff Layton7586b762008-12-01 18:41:49 -05004545 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004546 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004547 kfree(volume_info->username);
4548 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004549 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004551 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004553 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004554 /* In userspace mount helper we can get user name from alternate
4555 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004556 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557 }
4558
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004560 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004561 /* load_nls_default cannot return null */
4562 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004564 volume_info->local_nls = load_nls(volume_info->iocharset);
4565 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004566 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004567 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004568 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569 }
4570 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004571
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004572 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004573}
4574
4575struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004576cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004577{
4578 int rc;
4579 struct smb_vol *volume_info;
4580
Jeff Layton6ee95422012-11-26 11:09:57 -05004581 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004582 if (!volume_info)
4583 return ERR_PTR(-ENOMEM);
4584
Steve Frenchc7c137b2018-06-06 17:59:29 -05004585 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004586 if (rc) {
4587 cifs_cleanup_volume_info(volume_info);
4588 volume_info = ERR_PTR(rc);
4589 }
4590
4591 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004592}
4593
Aurelien Aptela6b50582016-05-25 19:59:09 +02004594static int
4595cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4596 unsigned int xid,
4597 struct cifs_tcon *tcon,
4598 struct cifs_sb_info *cifs_sb,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004599 char *full_path,
4600 int added_treename)
Aurelien Aptela6b50582016-05-25 19:59:09 +02004601{
4602 int rc;
4603 char *s;
4604 char sep, tmp;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004605 int skip = added_treename ? 1 : 0;
Aurelien Aptela6b50582016-05-25 19:59:09 +02004606
4607 sep = CIFS_DIR_SEP(cifs_sb);
4608 s = full_path;
4609
4610 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4611 while (rc == 0) {
4612 /* skip separators */
4613 while (*s == sep)
4614 s++;
4615 if (!*s)
4616 break;
4617 /* next separator */
4618 while (*s && *s != sep)
4619 s++;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004620 /*
4621 * if the treename is added, we then have to skip the first
4622 * part within the separators
4623 */
4624 if (skip) {
4625 skip = 0;
4626 continue;
4627 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004628 /*
4629 * temporarily null-terminate the path at the end of
4630 * the current component
4631 */
4632 tmp = *s;
4633 *s = 0;
4634 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4635 full_path);
4636 *s = tmp;
4637 }
4638 return rc;
4639}
4640
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004641/*
4642 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4643 * otherwise 0.
4644 */
4645static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4646 const unsigned int xid,
4647 struct TCP_Server_Info *server,
4648 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004649{
Jeff Layton1daaae82012-03-21 06:30:40 -04004650 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004651 char *full_path;
4652
4653 if (!server->ops->is_path_accessible)
4654 return -EOPNOTSUPP;
4655
4656 /*
4657 * cifs_build_path_to_root works only when we have a valid tcon
4658 */
4659 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4660 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4661 if (full_path == NULL)
4662 return -ENOMEM;
4663
4664 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4665
4666 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4667 full_path);
4668 if (rc != 0 && rc != -EREMOTE) {
4669 kfree(full_path);
4670 return rc;
4671 }
4672
4673 if (rc != -EREMOTE) {
4674 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004675 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004676 if (rc != 0) {
Joe Perchesa0a30362020-04-14 22:42:53 -07004677 cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004678 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4679 rc = 0;
4680 }
4681 }
4682
4683 kfree(full_path);
4684 return rc;
4685}
4686
4687#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004688static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4689 struct cifs_ses **root_ses)
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004690{
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004691 if (ses) {
4692 spin_lock(&cifs_tcp_ses_lock);
4693 ses->ses_count++;
4694 ses->tcon_ipc->remap = cifs_remap(cifs_sb);
4695 spin_unlock(&cifs_tcp_ses_lock);
4696 }
4697 *root_ses = ses;
4698}
4699
4700static void put_root_ses(struct cifs_ses *ses)
4701{
4702 if (ses)
4703 cifs_put_smb_ses(ses);
4704}
4705
4706/* Check if a path component is remote and then update @dfs_path accordingly */
4707static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4708 const unsigned int xid, struct TCP_Server_Info *server,
4709 struct cifs_tcon *tcon, char **dfs_path)
4710{
4711 char *path, *s;
4712 char sep = CIFS_DIR_SEP(cifs_sb), tmp;
4713 char *npath;
4714 int rc = 0;
4715 int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS;
4716 int skip = added_treename;
4717
4718 path = cifs_build_path_to_root(vol, cifs_sb, tcon, added_treename);
4719 if (!path)
4720 return -ENOMEM;
4721
4722 /*
4723 * Walk through the path components in @path and check if they're accessible. In case any of
4724 * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path
4725 * (NOT including the remaining components).
4726 */
4727 s = path;
4728 do {
4729 /* skip separators */
4730 while (*s && *s == sep)
4731 s++;
4732 if (!*s)
4733 break;
4734 /* next separator */
4735 while (*s && *s != sep)
4736 s++;
4737 /*
4738 * if the treename is added, we then have to skip the first
4739 * part within the separators
4740 */
4741 if (skip) {
4742 skip = 0;
4743 continue;
4744 }
4745 tmp = *s;
4746 *s = 0;
4747 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path);
4748 if (rc && rc == -EREMOTE) {
4749 struct smb_vol v = {NULL};
4750 /* if @path contains a tree name, skip it in the prefix path */
4751 if (added_treename) {
4752 rc = cifs_parse_devname(path, &v);
4753 if (rc)
4754 break;
4755 rc = -EREMOTE;
4756 npath = build_unc_path_to_root(&v, cifs_sb, true);
4757 cifs_cleanup_volume_info_contents(&v);
4758 } else {
4759 v.UNC = vol->UNC;
4760 v.prepath = path + 1;
4761 npath = build_unc_path_to_root(&v, cifs_sb, true);
4762 }
4763 if (IS_ERR(npath)) {
4764 rc = PTR_ERR(npath);
4765 break;
4766 }
4767 kfree(*dfs_path);
4768 *dfs_path = npath;
4769 }
4770 *s = tmp;
4771 } while (rc == 0);
4772
4773 kfree(path);
4774 return rc;
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004775}
4776
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004777int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4778{
4779 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004780 unsigned int xid;
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004781 struct TCP_Server_Info *server = NULL;
4782 struct cifs_ses *ses = NULL, *root_ses = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004783 struct cifs_tcon *tcon = NULL;
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004784 int count = 0;
4785 char *ref_path = NULL, *full_path = NULL;
4786 char *oldmnt = NULL;
4787 char *mntdata = NULL;
Al Virodd854462011-06-17 08:24:42 -04004788
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004789 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004790 /*
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004791 * Unconditionally try to get an DFS referral (even cached) to determine whether it is an
4792 * DFS mount.
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004793 *
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004794 * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem
4795 * to respond with PATH_NOT_COVERED to requests that include the prefix.
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004796 */
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004797 if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4798 NULL)) {
4799 /* No DFS referral was returned. Looks like a regular share. */
4800 if (rc)
4801 goto error;
4802 /* Check if it is fully accessible and then mount it */
4803 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4804 if (!rc)
4805 goto out;
4806 if (rc != -EREMOTE)
4807 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004808 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004809 /* Save mount options */
4810 mntdata = kstrndup(cifs_sb->mountdata, strlen(cifs_sb->mountdata), GFP_KERNEL);
4811 if (!mntdata) {
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004812 rc = -ENOMEM;
4813 goto error;
4814 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004815 /* Get path of DFS root */
4816 ref_path = build_unc_path_to_root(vol, cifs_sb, false);
4817 if (IS_ERR(ref_path)) {
4818 rc = PTR_ERR(ref_path);
4819 ref_path = NULL;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004820 goto error;
4821 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004822
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004823 set_root_ses(cifs_sb, ses, &root_ses);
4824 do {
4825 /* Save full path of last DFS path we used to resolve final target server */
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004826 kfree(full_path);
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004827 full_path = build_unc_path_to_root(vol, cifs_sb, !!count);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004828 if (IS_ERR(full_path)) {
4829 rc = PTR_ERR(full_path);
Dan Carpenter20b135e2020-08-05 12:52:07 +03004830 full_path = NULL;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004831 break;
4832 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004833 /* Chase referral */
4834 oldmnt = cifs_sb->mountdata;
4835 rc = expand_dfs_referral(xid, root_ses, vol, cifs_sb, ref_path + 1);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004836 if (rc)
4837 break;
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004838 /* Connect to new DFS target only if we were redirected */
4839 if (oldmnt != cifs_sb->mountdata) {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004840 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004841 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004842 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004843 if (rc && !server && !ses) {
4844 /* Failed to connect. Try to connect to other targets in the referral. */
4845 rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, vol, root_ses, &xid,
4846 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004847 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004848 if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses)
4849 break;
4850 if (!tcon)
4851 continue;
4852 /* Make sure that requests go through new root servers */
Paulo Alcantarae1837852020-08-27 11:20:19 -03004853 if (is_tcon_dfs(tcon)) {
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004854 put_root_ses(root_ses);
4855 set_root_ses(cifs_sb, ses, &root_ses);
4856 }
4857 /* Check for remaining path components and then continue chasing them (-EREMOTE) */
4858 rc = check_dfs_prepath(cifs_sb, vol, xid, server, tcon, &ref_path);
4859 /* Prevent recursion on broken link referrals */
4860 if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS)
4861 rc = -ELOOP;
4862 } while (rc == -EREMOTE);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004863
Jeff Layton9d002df2010-10-06 19:51:11 -04004864 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004865 goto error;
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004866 put_root_ses(root_ses);
4867 root_ses = NULL;
4868 kfree(ref_path);
4869 ref_path = NULL;
4870 /*
4871 * Store DFS full path in both superblock and tree connect structures.
4872 *
4873 * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so
4874 * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS
4875 * links, the prefix path is included in both and may be changed during reconnect. See
4876 * cifs_tree_connect().
4877 */
4878 cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004879 if (!cifs_sb->origin_fullpath) {
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004880 rc = -ENOMEM;
4881 goto error;
4882 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004883 spin_lock(&cifs_tcp_ses_lock);
4884 tcon->dfs_path = full_path;
4885 full_path = NULL;
4886 tcon->remap = cifs_remap(cifs_sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004887 spin_unlock(&cifs_tcp_ses_lock);
4888
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004889 /* Add original volume information for DFS cache to be used when refreshing referrals */
4890 rc = dfs_cache_add_vol(mntdata, vol, cifs_sb->origin_fullpath);
4891 if (rc)
Paulo Alcantarae511d312018-11-14 17:16:44 -02004892 goto error;
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004893 /*
4894 * After reconnecting to a different server, unique ids won't
4895 * match anymore, so we disable serverino. This prevents
4896 * dentry revalidation to think the dentry are stale (ESTALE).
4897 */
4898 cifs_autodisable_serverino(cifs_sb);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -03004899 /*
4900 * Force the use of prefix path to support failover on DFS paths that
4901 * resolve to targets that have different prefix paths.
4902 */
4903 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4904 kfree(cifs_sb->prepath);
4905 cifs_sb->prepath = vol->prepath;
4906 vol->prepath = NULL;
4907
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004908out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004909 free_xid(xid);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02004910 cifs_try_adding_channels(ses);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004911 return mount_setup_tlink(cifs_sb, ses, tcon);
4912
4913error:
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004914 kfree(ref_path);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004915 kfree(full_path);
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004916 kfree(mntdata);
4917 kfree(cifs_sb->origin_fullpath);
4918 put_root_ses(root_ses);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004919 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920 return rc;
4921}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004922#else
4923int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4924{
4925 int rc = 0;
4926 unsigned int xid;
4927 struct cifs_ses *ses;
4928 struct cifs_tcon *tcon;
4929 struct TCP_Server_Info *server;
4930
4931 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4932 if (rc)
4933 goto error;
4934
4935 if (tcon) {
4936 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4937 if (rc == -EREMOTE)
4938 rc = -EOPNOTSUPP;
4939 if (rc)
4940 goto error;
4941 }
4942
4943 free_xid(xid);
4944
4945 return mount_setup_tlink(cifs_sb, ses, tcon);
4946
4947error:
4948 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4949 return rc;
4950}
4951#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952
Jeff Layton8d1bca32011-06-11 21:17:10 -04004953/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01004954 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04004955 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04004957CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00004958 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959 const struct nls_table *nls_codepage)
4960{
4961 struct smb_hdr *smb_buffer;
4962 struct smb_hdr *smb_buffer_response;
4963 TCONX_REQ *pSMB;
4964 TCONX_RSP *pSMBr;
4965 unsigned char *bcc_ptr;
4966 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05004967 int length;
4968 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969
4970 if (ses == NULL)
4971 return -EIO;
4972
4973 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00004974 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004975 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00004976
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977 smb_buffer_response = smb_buffer;
4978
4979 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
4980 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07004981
Pavel Shilovsky88257362012-05-23 14:01:59 +04004982 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983 smb_buffer->Uid = ses->Suid;
4984 pSMB = (TCONX_REQ *) smb_buffer;
4985 pSMBr = (TCONX_RSP *) smb_buffer_response;
4986
4987 pSMB->AndXCommand = 0xFF;
4988 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01004990 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08004991 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00004992 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08004993 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00004994 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08004995 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004996 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08004997 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
4998 specified as required (when that support is added to
4999 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00005000 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08005001 by Samba (not sure whether other servers allow
5002 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00005003#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04005004 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05005005 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05005006 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00005007 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05005008 SECMODE_PW_ENCRYPT ? true : false,
5009 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00005010 else
5011#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06005012 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05005013 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05005014 if (rc) {
5015 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
5016 __func__, rc);
5017 cifs_buf_release(smb_buffer);
5018 return rc;
5019 }
Steve Frencheeac8042006-01-13 21:34:58 -08005020
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005021 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005022 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00005023 /* must align unicode strings */
5024 *bcc_ptr = 0; /* null byte password */
5025 bcc_ptr++;
5026 }
Steve Frencheeac8042006-01-13 21:34:58 -08005027 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028
Jeff Layton38d77c52013-05-26 07:01:00 -04005029 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005030 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
5031
5032 if (ses->capabilities & CAP_STATUS32) {
5033 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
5034 }
5035 if (ses->capabilities & CAP_DFS) {
5036 smb_buffer->Flags2 |= SMBFLG2_DFS;
5037 }
5038 if (ses->capabilities & CAP_UNICODE) {
5039 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
5040 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06005041 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00005042 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00005043 (/* server len*/ + 256 /* share len */), nls_codepage);
5044 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045 bcc_ptr += 2; /* skip trailing null */
5046 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005047 strcpy(bcc_ptr, tree);
5048 bcc_ptr += strlen(tree) + 1;
5049 }
5050 strcpy(bcc_ptr, "?????");
5051 bcc_ptr += strlen("?????");
5052 bcc_ptr += 1;
5053 count = bcc_ptr - &pSMB->Password[0];
Qinglang Miao1a0e7f72020-07-25 16:56:01 +08005054 be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055 pSMB->ByteCount = cpu_to_le16(count);
5056
Steve French133672e2007-11-13 22:41:37 +00005057 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05005058 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01005061 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00005062 bool is_unicode;
5063
Linus Torvalds1da177e2005-04-16 15:20:36 -07005064 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00005065 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066 tcon->tid = smb_buffer_response->Tid;
5067 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05005068 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005069 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00005070 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
5071 is_unicode = true;
5072 else
5073 is_unicode = false;
5074
Jeff Laytoncc20c032009-04-30 07:16:21 -04005075
Steve French50c2f752007-07-13 00:33:32 +00005076 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00005077 if (length == 3) {
5078 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
5079 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05005080 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01005081 tcon->ipc = true;
5082 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00005083 }
5084 } else if (length == 2) {
5085 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
5086 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05005087 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00005088 }
5089 }
Steve French50c2f752007-07-13 00:33:32 +00005090 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04005091 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05005092 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04005093
5094 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04005095 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06005096 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00005097 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04005098 nls_codepage);
5099
Joe Perchesf96637b2013-05-04 22:12:25 -05005100 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005101
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005102 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00005103 (smb_buffer_response->WordCount == 7))
5104 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00005105 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
5106 else
5107 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05005108 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109 }
5110
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00005111 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112 return rc;
5113}
5114
Al Viro2e32cf52013-10-03 12:53:37 -04005115static void delayed_free(struct rcu_head *p)
5116{
5117 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
5118 unload_nls(sbi->local_nls);
5119 kfree(sbi);
5120}
5121
Al Viro2a9b9952011-06-17 09:27:16 -04005122void
5123cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005124{
Jeff Laytonb647c352010-10-28 11:16:44 -04005125 struct rb_root *root = &cifs_sb->tlink_tree;
5126 struct rb_node *node;
5127 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128
Jeff Layton2de970f2010-10-06 19:51:12 -04005129 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
5130
Jeff Laytonb647c352010-10-28 11:16:44 -04005131 spin_lock(&cifs_sb->tlink_tree_lock);
5132 while ((node = rb_first(root))) {
5133 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5134 cifs_get_tlink(tlink);
5135 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5136 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00005137
Jeff Laytonb647c352010-10-28 11:16:44 -04005138 spin_unlock(&cifs_sb->tlink_tree_lock);
5139 cifs_put_tlink(tlink);
5140 spin_lock(&cifs_sb->tlink_tree_lock);
5141 }
5142 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005143
Al Virod757d712011-06-17 09:42:43 -04005144 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02005145 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005146#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02005147 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005148 kfree(cifs_sb->origin_fullpath);
5149#endif
Al Viro2e32cf52013-10-03 12:53:37 -04005150 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00005151}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005153int
5154cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005155{
5156 int rc = 0;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005157 struct TCP_Server_Info *server = cifs_ses_server(ses);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005158
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005159 if (!server->ops->need_neg || !server->ops->negotiate)
5160 return -ENOSYS;
5161
Jeff Layton198b5682010-04-24 07:57:48 -04005162 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005163 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04005164 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005165
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005166 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005167 if (rc == 0) {
5168 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04005169 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04005170 server->tcpStatus = CifsGood;
5171 else
5172 rc = -EHOSTDOWN;
5173 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005174 }
Steve French26b994f2008-08-06 05:11:33 +00005175
Jeff Layton198b5682010-04-24 07:57:48 -04005176 return rc;
5177}
Steve French26b994f2008-08-06 05:11:33 +00005178
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005179int
5180cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
5181 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04005182{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005183 int rc = -ENOSYS;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005184 struct TCP_Server_Info *server = cifs_ses_server(ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005185
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02005186 if (!ses->binding) {
5187 ses->capabilities = server->capabilities;
5188 if (linuxExtEnabled == 0)
5189 ses->capabilities &= (~server->vals->cap_unix);
5190
5191 if (ses->auth_key.response) {
5192 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
5193 ses->auth_key.response);
5194 kfree(ses->auth_key.response);
5195 ses->auth_key.response = NULL;
5196 ses->auth_key.len = 0;
5197 }
5198 }
Steve French20418ac2009-04-30 16:13:32 +00005199
Joe Perchesf96637b2013-05-04 22:12:25 -05005200 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00005201 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04005202
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005203 if (server->ops->sess_setup)
5204 rc = server->ops->sess_setup(xid, ses, nls_info);
5205
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05005206 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10005207 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05005208
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209 return rc;
5210}
5211
Jeff Layton8a8798a2012-01-17 16:09:15 -05005212static int
5213cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
5214{
Jeff Layton3f618222013-06-12 19:52:14 -05005215 vol->sectype = ses->sectype;
5216
5217 /* krb5 is special, since we don't need username or pw */
5218 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05005219 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05005220
5221 return cifs_set_cifscreds(vol, ses);
5222}
5223
Steve French96daf2b2011-05-27 04:34:02 +00005224static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005225cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04005226{
Jeff Layton8a8798a2012-01-17 16:09:15 -05005227 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00005228 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
5229 struct cifs_ses *ses;
5230 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04005231 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04005232
5233 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03005234 if (vol_info == NULL)
5235 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04005236
Jeff Layton9d002df2010-10-06 19:51:11 -04005237 vol_info->local_nls = cifs_sb->local_nls;
5238 vol_info->linux_uid = fsuid;
5239 vol_info->cred_uid = fsuid;
5240 vol_info->UNC = master_tcon->treeName;
5241 vol_info->retry = master_tcon->retry;
5242 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05005243 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04005244 vol_info->local_lease = master_tcon->local_lease;
Paul Aurichad35f162020-06-26 12:58:07 -07005245 vol_info->no_lease = master_tcon->no_lease;
Paul Aurich00dfbc22020-06-26 12:58:06 -07005246 vol_info->resilient = master_tcon->use_resilient;
5247 vol_info->persistent = master_tcon->use_persistent;
Paul Aurich6b356f6c2020-06-26 12:58:08 -07005248 vol_info->handle_timeout = master_tcon->handle_timeout;
Jeff Layton9d002df2010-10-06 19:51:11 -04005249 vol_info->no_linux_ext = !master_tcon->unix_ext;
Paul Aurich5391b8e2020-06-26 12:58:09 -07005250 vol_info->linux_ext = master_tcon->posix_extensions;
Jeff Layton28e11bd2013-05-26 07:01:00 -04005251 vol_info->sectype = master_tcon->ses->sectype;
5252 vol_info->sign = master_tcon->ses->sign;
Paul Aurichcc154612020-06-26 12:58:05 -07005253 vol_info->seal = master_tcon->seal;
Jeff Layton9d002df2010-10-06 19:51:11 -04005254
Jeff Layton8a8798a2012-01-17 16:09:15 -05005255 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
5256 if (rc) {
5257 tcon = ERR_PTR(rc);
5258 goto out;
5259 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005260
5261 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305262 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005263 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305264 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005265
5266 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
5267 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00005268 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07005269 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04005270 goto out;
5271 }
5272
5273 tcon = cifs_get_tcon(ses, vol_info);
5274 if (IS_ERR(tcon)) {
5275 cifs_put_smb_ses(ses);
5276 goto out;
5277 }
5278
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005279 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04005280 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05005281
Jeff Layton9d002df2010-10-06 19:51:11 -04005282out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05005283 kfree(vol_info->username);
Waiman Long453431a2020-08-06 23:18:13 -07005284 kfree_sensitive(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005285 kfree(vol_info);
5286
5287 return tcon;
5288}
5289
Steve French96daf2b2011-05-27 04:34:02 +00005290struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005291cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5292{
5293 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5294}
5295
Jeff Laytonb647c352010-10-28 11:16:44 -04005296/* find and return a tlink with given uid */
5297static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005298tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005299{
5300 struct rb_node *node = root->rb_node;
5301 struct tcon_link *tlink;
5302
5303 while (node) {
5304 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5305
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005306 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005307 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005308 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005309 node = node->rb_right;
5310 else
5311 return tlink;
5312 }
5313 return NULL;
5314}
5315
5316/* insert a tcon_link into the tree */
5317static void
5318tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5319{
5320 struct rb_node **new = &(root->rb_node), *parent = NULL;
5321 struct tcon_link *tlink;
5322
5323 while (*new) {
5324 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5325 parent = *new;
5326
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005327 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005328 new = &((*new)->rb_left);
5329 else
5330 new = &((*new)->rb_right);
5331 }
5332
5333 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5334 rb_insert_color(&new_tlink->tl_rbnode, root);
5335}
5336
Jeff Layton9d002df2010-10-06 19:51:11 -04005337/*
5338 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5339 * current task.
5340 *
5341 * If the superblock doesn't refer to a multiuser mount, then just return
5342 * the master tcon for the mount.
5343 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305344 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005345 * exists, then check to see if it's pending construction. If it is then wait
5346 * for construction to complete. Once it's no longer pending, check to see if
5347 * it failed and either return an error or retry construction, depending on
5348 * the timeout.
5349 *
5350 * If one doesn't exist then insert a new tcon_link struct into the tree and
5351 * try to construct a new one.
5352 */
5353struct tcon_link *
5354cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5355{
5356 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005357 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005358 struct tcon_link *tlink, *newtlink;
5359
5360 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5361 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5362
5363 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005364 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005365 if (tlink)
5366 cifs_get_tlink(tlink);
5367 spin_unlock(&cifs_sb->tlink_tree_lock);
5368
5369 if (tlink == NULL) {
5370 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5371 if (newtlink == NULL)
5372 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005373 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005374 newtlink->tl_tcon = ERR_PTR(-EACCES);
5375 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5376 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5377 cifs_get_tlink(newtlink);
5378
Jeff Layton9d002df2010-10-06 19:51:11 -04005379 spin_lock(&cifs_sb->tlink_tree_lock);
5380 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005381 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005382 if (tlink) {
5383 cifs_get_tlink(tlink);
5384 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005385 kfree(newtlink);
5386 goto wait_for_construction;
5387 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005388 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005389 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5390 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005391 } else {
5392wait_for_construction:
5393 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005394 TASK_INTERRUPTIBLE);
5395 if (ret) {
5396 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005397 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005398 }
5399
5400 /* if it's good, return it */
5401 if (!IS_ERR(tlink->tl_tcon))
5402 return tlink;
5403
5404 /* return error if we tried this already recently */
5405 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5406 cifs_put_tlink(tlink);
5407 return ERR_PTR(-EACCES);
5408 }
5409
5410 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5411 goto wait_for_construction;
5412 }
5413
5414 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5415 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5416 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5417
5418 if (IS_ERR(tlink->tl_tcon)) {
5419 cifs_put_tlink(tlink);
5420 return ERR_PTR(-EACCES);
5421 }
5422
5423 return tlink;
5424}
Jeff Layton2de970f2010-10-06 19:51:12 -04005425
5426/*
5427 * periodic workqueue job that scans tcon_tree for a superblock and closes
5428 * out tcons.
5429 */
5430static void
5431cifs_prune_tlinks(struct work_struct *work)
5432{
5433 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5434 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005435 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005436 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005437 struct rb_node *tmp;
5438 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005439
Jeff Laytonb647c352010-10-28 11:16:44 -04005440 /*
5441 * Because we drop the spinlock in the loop in order to put the tlink
5442 * it's not guarded against removal of links from the tree. The only
5443 * places that remove entries from the tree are this function and
5444 * umounts. Because this function is non-reentrant and is canceled
5445 * before umount can proceed, this is safe.
5446 */
5447 spin_lock(&cifs_sb->tlink_tree_lock);
5448 node = rb_first(root);
5449 while (node != NULL) {
5450 tmp = node;
5451 node = rb_next(tmp);
5452 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5453
5454 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5455 atomic_read(&tlink->tl_count) != 0 ||
5456 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5457 continue;
5458
5459 cifs_get_tlink(tlink);
5460 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5461 rb_erase(tmp, root);
5462
Jeff Layton2de970f2010-10-06 19:51:12 -04005463 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005464 cifs_put_tlink(tlink);
5465 spin_lock(&cifs_sb->tlink_tree_lock);
5466 }
5467 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005468
Jeff Laytonda472fc2012-03-23 14:40:53 -04005469 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005470 TLINK_IDLE_EXPIRE);
5471}
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005472
5473#ifdef CONFIG_CIFS_DFS_UPCALL
5474int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
5475{
5476 int rc;
5477 struct TCP_Server_Info *server = tcon->ses->server;
5478 const struct smb_version_operations *ops = server->ops;
5479 struct dfs_cache_tgt_list tl;
5480 struct dfs_cache_tgt_iterator *it = NULL;
5481 char *tree;
5482 const char *tcp_host;
5483 size_t tcp_host_len;
5484 const char *dfs_host;
5485 size_t dfs_host_len;
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005486 char *share = NULL, *prefix = NULL;
Paulo Alcantara11375a52020-07-21 09:36:43 -03005487 struct dfs_info3_param ref = {0};
5488 bool isroot;
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005489
5490 tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
5491 if (!tree)
5492 return -ENOMEM;
5493
5494 if (!tcon->dfs_path) {
5495 if (tcon->ipc) {
5496 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
5497 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5498 } else {
5499 rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
5500 }
5501 goto out;
5502 }
5503
Paulo Alcantara11375a52020-07-21 09:36:43 -03005504 rc = dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005505 if (rc)
5506 goto out;
Paulo Alcantara11375a52020-07-21 09:36:43 -03005507 isroot = ref.server_type == DFS_TYPE_ROOT;
5508 free_dfs_info_param(&ref);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005509
5510 extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
5511
5512 for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) {
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005513 bool target_match;
5514
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005515 kfree(share);
5516 kfree(prefix);
Colin Ian Kingc6a80e12020-07-31 18:13:42 +01005517 share = NULL;
5518 prefix = NULL;
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005519
5520 rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005521 if (rc) {
5522 cifs_dbg(VFS, "%s: failed to parse target share %d\n",
5523 __func__, rc);
5524 continue;
5525 }
5526
5527 extract_unc_hostname(share, &dfs_host, &dfs_host_len);
5528
5529 if (dfs_host_len != tcp_host_len
5530 || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
5531 cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
5532 dfs_host, (int)tcp_host_len, tcp_host);
5533
5534 rc = match_target_ip(server, dfs_host, dfs_host_len, &target_match);
5535 if (rc) {
5536 cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
5537 break;
5538 }
5539
5540 if (!target_match) {
5541 cifs_dbg(FYI, "%s: skipping target\n", __func__);
5542 continue;
5543 }
5544 }
5545
5546 if (tcon->ipc) {
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005547 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005548 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5549 } else {
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005550 scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005551 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
Paulo Alcantara11375a52020-07-21 09:36:43 -03005552 /* Only handle prefix paths of DFS link targets */
5553 if (!rc && !isroot) {
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005554 rc = update_super_prepath(tcon, prefix);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005555 break;
5556 }
5557 }
5558 if (rc == -EREMOTE)
5559 break;
5560 }
5561
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005562 kfree(share);
5563 kfree(prefix);
5564
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005565 if (!rc) {
5566 if (it)
5567 rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it);
5568 else
5569 rc = -ENOENT;
5570 }
5571 dfs_cache_free_tgts(&tl);
5572out:
5573 kfree(tree);
5574 return rc;
5575}
5576#else
5577int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
5578{
5579 const struct smb_version_operations *ops = tcon->ses->server->ops;
5580
5581 return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
5582}
5583#endif