blob: a5731dd6e6566e7f86bac2db176f3c640a4d266f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/connect.c
3 *
Steve French1080ef72011-02-24 18:07:19 +00004 * Copyright (C) International Business Machines Corp., 2002,2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
Steve Frenchfb8c4b12007-07-10 01:16:18 +000019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
Eric Biggersdc920272020-03-08 22:58:20 -070024#include <linux/sched/mm.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010025#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/list.h>
27#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090028#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/pagemap.h>
30#include <linux/ctype.h>
31#include <linux/utsname.h>
32#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070033#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070034#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000035#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070036#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080037#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040038#include <linux/namei.h>
Andrew Lunnc6e970a2017-03-28 23:45:06 +020039#include <linux/uuid.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080040#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040042#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040043#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050044#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000045#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040046#include <linux/parser.h>
Christoph Hellwig2f8b5442016-11-01 07:40:13 -060047#include <linux/bvec.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include "cifspdu.h"
49#include "cifsglob.h"
50#include "cifsproto.h"
51#include "cifs_unicode.h"
52#include "cifs_debug.h"
53#include "cifs_fs_sb.h"
54#include "ntlmssp.h"
55#include "nterr.h"
56#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053057#include "fscache.h"
Pavel Shilovsky53e0e112016-11-04 11:50:31 -070058#include "smb2proto.h"
Long Li2f894642017-11-22 17:38:34 -070059#include "smbdirect.h"
Paulo Alcantara1c780222018-11-14 16:24:03 -020060#include "dns_resolve.h"
61#ifdef CONFIG_CIFS_DFS_UPCALL
62#include "dfs_cache.h"
63#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Linus Torvalds1da177e2005-04-16 15:20:36 -070065extern mempool_t *cifs_req_poolp;
Steve Frenchf92a7202018-05-24 04:11:07 -050066extern bool disable_legacy_dialects;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Jeff Layton2de970f2010-10-06 19:51:12 -040068/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040069#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040070#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040071
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040072enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040073 /* Mount options that take no arguments */
74 Opt_user_xattr, Opt_nouser_xattr,
75 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040076 Opt_forcegid, Opt_noforcegid,
Steve French3e7a02d2019-09-11 21:46:20 -050077 Opt_noblocksend, Opt_noautotune, Opt_nolease,
Steve French82e93672020-05-19 03:06:57 -050078 Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_nodelete,
Steve French2baa2682014-09-27 02:19:01 -050079 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040080 Opt_mapchars, Opt_nomapchars, Opt_sfu,
81 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
Steve Frenchb3266142018-05-20 23:41:10 -050082 Opt_noposixpaths, Opt_nounix, Opt_unix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040083 Opt_nocase,
84 Opt_brl, Opt_nobrl,
Steve French3d4ef9a2018-04-25 22:19:09 -050085 Opt_handlecache, Opt_nohandlecache,
Steve French95932652016-09-23 01:36:34 -050086 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040087 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
88 Opt_nohard, Opt_nosoft,
89 Opt_nointr, Opt_intr,
90 Opt_nostrictsync, Opt_strictsync,
91 Opt_serverino, Opt_noserverino,
92 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
93 Opt_acl, Opt_noacl, Opt_locallease,
Steve French4f5c10f2019-09-03 21:18:49 -050094 Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040095 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -040096 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -050097 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -060098 Opt_resilient, Opt_noresilient,
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -030099 Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200100 Opt_multichannel, Opt_nomultichannel,
Steve French9fe5ff12019-06-24 20:39:04 -0500101 Opt_compress,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400102
103 /* Mount options which take numeric value */
104 Opt_backupuid, Opt_backupgid, Opt_uid,
105 Opt_cruid, Opt_gid, Opt_file_mode,
106 Opt_dirmode, Opt_port,
Steve French563317e2019-09-08 23:22:02 -0500107 Opt_min_enc_offload,
Steve Frenche8506d22019-02-28 21:32:15 -0600108 Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
Steve Frenchca567eb2019-03-29 16:31:07 -0500109 Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200110 Opt_snapshot, Opt_max_channels,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400111
112 /* Mount options which take string value */
113 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400114 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400115 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400116 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400117
118 /* Mount options to be ignored */
119 Opt_ignore,
120
121 /* Options which could be blank */
122 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100123 Opt_blank_user,
124 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400125
126 Opt_err
127};
128
129static const match_table_t cifs_mount_option_tokens = {
130
131 { Opt_user_xattr, "user_xattr" },
132 { Opt_nouser_xattr, "nouser_xattr" },
133 { Opt_forceuid, "forceuid" },
134 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400135 { Opt_forcegid, "forcegid" },
136 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400137 { Opt_noblocksend, "noblocksend" },
138 { Opt_noautotune, "noautotune" },
Steve French3e7a02d2019-09-11 21:46:20 -0500139 { Opt_nolease, "nolease" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400140 { Opt_hard, "hard" },
141 { Opt_soft, "soft" },
142 { Opt_perm, "perm" },
143 { Opt_noperm, "noperm" },
Steve French82e93672020-05-19 03:06:57 -0500144 { Opt_nodelete, "nodelete" },
Steve French2baa2682014-09-27 02:19:01 -0500145 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400146 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500147 { Opt_mapposix, "mapposix" }, /* SFM style */
148 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400149 { Opt_sfu, "sfu" },
150 { Opt_nosfu, "nosfu" },
151 { Opt_nodfs, "nodfs" },
152 { Opt_posixpaths, "posixpaths" },
153 { Opt_noposixpaths, "noposixpaths" },
154 { Opt_nounix, "nounix" },
155 { Opt_nounix, "nolinux" },
Steve Frenchb3266142018-05-20 23:41:10 -0500156 { Opt_nounix, "noposix" },
157 { Opt_unix, "unix" },
158 { Opt_unix, "linux" },
159 { Opt_unix, "posix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400160 { Opt_nocase, "nocase" },
161 { Opt_nocase, "ignorecase" },
162 { Opt_brl, "brl" },
163 { Opt_nobrl, "nobrl" },
Steve French3d4ef9a2018-04-25 22:19:09 -0500164 { Opt_handlecache, "handlecache" },
165 { Opt_nohandlecache, "nohandlecache" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400166 { Opt_nobrl, "nolock" },
167 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400168 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400169 { Opt_setuids, "setuids" },
170 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500171 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400172 { Opt_dynperm, "dynperm" },
173 { Opt_nodynperm, "nodynperm" },
174 { Opt_nohard, "nohard" },
175 { Opt_nosoft, "nosoft" },
176 { Opt_nointr, "nointr" },
177 { Opt_intr, "intr" },
178 { Opt_nostrictsync, "nostrictsync" },
179 { Opt_strictsync, "strictsync" },
180 { Opt_serverino, "serverino" },
181 { Opt_noserverino, "noserverino" },
182 { Opt_rwpidforward, "rwpidforward" },
Steve French412094a2019-06-24 02:01:42 -0500183 { Opt_modesid, "modefromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400184 { Opt_cifsacl, "cifsacl" },
185 { Opt_nocifsacl, "nocifsacl" },
186 { Opt_acl, "acl" },
187 { Opt_noacl, "noacl" },
188 { Opt_locallease, "locallease" },
189 { Opt_sign, "sign" },
Steve French4f5c10f2019-09-03 21:18:49 -0500190 { Opt_ignore_signature, "signloosely" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400191 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400192 { Opt_noac, "noac" },
193 { Opt_fsc, "fsc" },
194 { Opt_mfsymlinks, "mfsymlinks" },
195 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400196 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400197 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500198 { Opt_persistent, "persistenthandles"},
199 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600200 { Opt_resilient, "resilienthandles"},
201 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530202 { Opt_domainauto, "domainauto"},
Long Li8339dd32017-11-07 01:54:55 -0700203 { Opt_rdma, "rdma"},
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200204 { Opt_multichannel, "multichannel" },
205 { Opt_nomultichannel, "nomultichannel" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400206
207 { Opt_backupuid, "backupuid=%s" },
208 { Opt_backupgid, "backupgid=%s" },
209 { Opt_uid, "uid=%s" },
210 { Opt_cruid, "cruid=%s" },
211 { Opt_gid, "gid=%s" },
212 { Opt_file_mode, "file_mode=%s" },
213 { Opt_dirmode, "dirmode=%s" },
214 { Opt_dirmode, "dir_mode=%s" },
215 { Opt_port, "port=%s" },
Steve French563317e2019-09-08 23:22:02 -0500216 { Opt_min_enc_offload, "esize=%s" },
Steve Frenche8506d22019-02-28 21:32:15 -0600217 { Opt_blocksize, "bsize=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400218 { Opt_rsize, "rsize=%s" },
219 { Opt_wsize, "wsize=%s" },
220 { Opt_actimeo, "actimeo=%s" },
Steve Frenchca567eb2019-03-29 16:31:07 -0500221 { Opt_handletimeout, "handletimeout=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600222 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500223 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600224 { Opt_snapshot, "snapshot=%s" },
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200225 { Opt_max_channels, "max_channels=%s" },
Steve French9fe5ff12019-06-24 20:39:04 -0500226 { Opt_compress, "compress=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400227
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100228 { Opt_blank_user, "user=" },
229 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400230 { Opt_user, "user=%s" },
231 { Opt_user, "username=%s" },
232 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100233 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400234 { Opt_pass, "pass=%s" },
235 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100236 { Opt_blank_ip, "ip=" },
237 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400238 { Opt_ip, "ip=%s" },
239 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400240 { Opt_ignore, "unc=%s" },
241 { Opt_ignore, "target=%s" },
242 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400243 { Opt_domain, "dom=%s" },
244 { Opt_domain, "domain=%s" },
245 { Opt_domain, "workgroup=%s" },
246 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400247 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400248 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400249 { Opt_netbiosname, "netbiosname=%s" },
250 { Opt_servern, "servern=%s" },
251 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400252 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400253 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400254 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400255
256 { Opt_ignore, "cred" },
257 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400258 { Opt_ignore, "cred=%s" },
259 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400260 { Opt_ignore, "guest" },
261 { Opt_ignore, "rw" },
262 { Opt_ignore, "ro" },
263 { Opt_ignore, "suid" },
264 { Opt_ignore, "nosuid" },
265 { Opt_ignore, "exec" },
266 { Opt_ignore, "noexec" },
267 { Opt_ignore, "nodev" },
268 { Opt_ignore, "noauto" },
269 { Opt_ignore, "dev" },
270 { Opt_ignore, "mand" },
271 { Opt_ignore, "nomand" },
Steve French9b9c5be2018-09-22 12:07:06 -0500272 { Opt_ignore, "relatime" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400273 { Opt_ignore, "_netdev" },
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -0300274 { Opt_rootfs, "rootfs" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400275
276 { Opt_err, NULL }
277};
278
279enum {
280 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
281 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400282 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
283 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400284 Opt_sec_none,
285
286 Opt_sec_err
287};
288
289static const match_table_t cifs_secflavor_tokens = {
290 { Opt_sec_krb5, "krb5" },
291 { Opt_sec_krb5i, "krb5i" },
292 { Opt_sec_krb5p, "krb5p" },
293 { Opt_sec_ntlmsspi, "ntlmsspi" },
294 { Opt_sec_ntlmssp, "ntlmssp" },
295 { Opt_ntlm, "ntlm" },
296 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400297 { Opt_sec_ntlmv2, "nontlm" },
298 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400299 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400300 { Opt_sec_lanman, "lanman" },
301 { Opt_sec_none, "none" },
302
303 { Opt_sec_err, NULL }
304};
305
Jeff Layton15b6a472012-05-16 07:50:15 -0400306/* cache flavors */
307enum {
308 Opt_cache_loose,
309 Opt_cache_strict,
310 Opt_cache_none,
Steve French83bbfa72019-08-27 23:58:54 -0500311 Opt_cache_ro,
Steve French41e033f2019-08-30 02:12:41 -0500312 Opt_cache_rw,
Jeff Layton15b6a472012-05-16 07:50:15 -0400313 Opt_cache_err
314};
315
316static const match_table_t cifs_cacheflavor_tokens = {
317 { Opt_cache_loose, "loose" },
318 { Opt_cache_strict, "strict" },
319 { Opt_cache_none, "none" },
Steve French83bbfa72019-08-27 23:58:54 -0500320 { Opt_cache_ro, "ro" },
Steve French41e033f2019-08-30 02:12:41 -0500321 { Opt_cache_rw, "singleclient" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400322 { Opt_cache_err, NULL }
323};
324
Jeff Layton23db65f2012-05-15 12:20:51 -0400325static const match_table_t cifs_smb_version_tokens = {
326 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600327 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000328 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500329 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500330 { Smb_302, SMB302_VERSION_STRING },
Kenneth D'souza4a3b38a2018-11-17 10:33:30 +0530331 { Smb_302, ALT_SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600332 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500333 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French9764c022017-09-17 10:41:35 -0500334 { Smb_3any, SMB3ANY_VERSION_STRING },
335 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600336 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400337};
338
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300339static int ip_connect(struct TCP_Server_Info *server);
340static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400341static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400342static void cifs_prune_tlinks(struct work_struct *work);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200343static char *extract_hostname(const char *unc);
344
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200345/*
346 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
347 * get their ip addresses changed at some point.
348 *
349 * This should be called with server->srv_mutex held.
350 */
351#ifdef CONFIG_CIFS_DFS_UPCALL
352static int reconn_set_ipaddr(struct TCP_Server_Info *server)
353{
354 int rc;
355 int len;
356 char *unc, *ipaddr = NULL;
357
358 if (!server->hostname)
359 return -EINVAL;
360
361 len = strlen(server->hostname) + 3;
362
363 unc = kmalloc(len, GFP_KERNEL);
364 if (!unc) {
365 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
366 return -ENOMEM;
367 }
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +1000368 scnprintf(unc, len, "\\\\%s", server->hostname);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200369
370 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
371 kfree(unc);
372
373 if (rc < 0) {
374 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
375 __func__, server->hostname, rc);
376 return rc;
377 }
378
Ronnie Sahlbergfada37f2020-04-21 12:37:39 +1000379 spin_lock(&cifs_tcp_ses_lock);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200380 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
381 strlen(ipaddr));
Ronnie Sahlbergfada37f2020-04-21 12:37:39 +1000382 spin_unlock(&cifs_tcp_ses_lock);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200383 kfree(ipaddr);
384
385 return !rc ? -1 : 0;
386}
387#else
388static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
389{
390 return 0;
391}
392#endif
393
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200394#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200395/* These functions must be called with server->srv_mutex held */
Paulo Alcantara7d397a02020-07-21 09:36:40 -0300396static void reconn_set_next_dfs_target(struct TCP_Server_Info *server,
397 struct cifs_sb_info *cifs_sb,
398 struct dfs_cache_tgt_list *tgt_list,
399 struct dfs_cache_tgt_iterator **tgt_it)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200400{
401 const char *name;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200402
Paulo Alcantara7d397a02020-07-21 09:36:40 -0300403 if (!cifs_sb || !cifs_sb->origin_fullpath)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200404 return;
405
406 if (!*tgt_it) {
407 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
408 } else {
409 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
410 if (!*tgt_it)
411 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
412 }
413
414 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
415
416 name = dfs_cache_get_tgt_name(*tgt_it);
417
418 kfree(server->hostname);
419
420 server->hostname = extract_hostname(name);
Dan Carpenter84288172019-01-05 15:25:29 +0300421 if (IS_ERR(server->hostname)) {
422 cifs_dbg(FYI,
423 "%s: failed to extract hostname from target: %ld\n",
424 __func__, PTR_ERR(server->hostname));
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200425 }
426}
427
428static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
Paulo Alcantarabaf3f082020-05-19 15:38:29 -0300429 struct dfs_cache_tgt_list *tl)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200430{
431 if (!cifs_sb->origin_fullpath)
432 return -EOPNOTSUPP;
433 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
434}
435#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Jeff Laytond5c56052008-12-01 18:42:33 -0500437/*
438 * cifs tcp session reconnection
439 *
440 * mark tcp session as reconnecting so temporarily locked
441 * mark all smb sessions as reconnecting for tcp session
442 * reconnect tcp session
443 * wake up waiters on reconnection? - (not needed currently)
444 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400445int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446cifs_reconnect(struct TCP_Server_Info *server)
447{
448 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500449 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000450 struct cifs_ses *ses;
451 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000452 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400453 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200454#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300455 struct super_block *sb = NULL;
Paulo Alcantara23324402018-11-20 14:37:18 -0200456 struct cifs_sb_info *cifs_sb = NULL;
457 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200458 struct dfs_cache_tgt_iterator *tgt_it = NULL;
459#endif
Steve French50c2f752007-07-13 00:33:32 +0000460
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200462 server->nr_targets = 1;
463#ifdef CONFIG_CIFS_DFS_UPCALL
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000464 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -0300465 sb = cifs_get_tcp_super(server);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300466 if (IS_ERR(sb)) {
467 rc = PTR_ERR(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200468 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
469 __func__, rc);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300470 sb = NULL;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200471 } else {
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300472 cifs_sb = CIFS_SB(sb);
Paulo Alcantarabaf3f082020-05-19 15:38:29 -0300473 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list);
Paulo Alcantaraa5293032020-07-21 09:36:41 -0300474 if (rc) {
475 cifs_sb = NULL;
476 if (rc != -EOPNOTSUPP) {
477 cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
478 __func__);
479 }
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200480 } else {
481 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
482 }
483 }
484 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
485 server->nr_targets);
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000486 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200487#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000488 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000489 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 next time through the loop */
491 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300492#ifdef CONFIG_CIFS_DFS_UPCALL
493 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -0300494 cifs_put_tcp_super(sb);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300495#endif
Stefan Metzmachere2e87512020-02-24 14:31:02 -0600496 wake_up(&server->response_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 return rc;
498 } else
499 server->tcpStatus = CifsNeedReconnect;
500 spin_unlock(&GlobalMid_Lock);
501 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400502 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
Steve French6e4d3bb2018-09-22 11:25:04 -0500504 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500505 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507 /* before reconnecting the tcp session, mark the smb session (uid)
508 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500509 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
510 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530511 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500512 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000513 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500514 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500515 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000516 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500517 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100519 if (ses->tcon_ipc)
520 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530522 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500523
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500525 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500526 mutex_lock(&server->srv_mutex);
Long Li1d2a4f52019-05-13 21:01:28 -0700527 if (server->ssocket) {
528 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
529 server->ssocket->state, server->ssocket->flags);
530 kernel_sock_shutdown(server->ssocket, SHUT_WR);
531 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
532 server->ssocket->state, server->ssocket->flags);
533 sock_release(server->ssocket);
534 server->ssocket = NULL;
535 }
536 server->sequence_number = 0;
537 server->session_estab = false;
538 kfree(server->session_key.response);
539 server->session_key.response = NULL;
540 server->session_key.len = 0;
541 server->lstrp = jiffies;
Long Li214bab42019-04-05 21:36:35 +0000542
543 /* mark submitted MIDs for retry and issue callback */
544 INIT_LIST_HEAD(&retry_list);
545 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
546 spin_lock(&GlobalMid_Lock);
547 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
548 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700549 kref_get(&mid_entry->refcount);
Long Li214bab42019-04-05 21:36:35 +0000550 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
551 mid_entry->mid_state = MID_RETRY_NEEDED;
552 list_move(&mid_entry->qhead, &retry_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700553 mid_entry->mid_flags |= MID_DELETED;
Long Li214bab42019-04-05 21:36:35 +0000554 }
555 spin_unlock(&GlobalMid_Lock);
Long Li1d2a4f52019-05-13 21:01:28 -0700556 mutex_unlock(&server->srv_mutex);
Long Li214bab42019-04-05 21:36:35 +0000557
558 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
559 list_for_each_safe(tmp, tmp2, &retry_list) {
560 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
561 list_del_init(&mid_entry->qhead);
562 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700563 cifs_mid_q_entry_release(mid_entry);
Long Li214bab42019-04-05 21:36:35 +0000564 }
565
Long Li1d2a4f52019-05-13 21:01:28 -0700566 if (cifs_rdma_enabled(server)) {
567 mutex_lock(&server->srv_mutex);
Long Li050b8c32019-04-04 11:35:42 -0500568 smbd_destroy(server);
Long Li1d2a4f52019-05-13 21:01:28 -0700569 mutex_unlock(&server->srv_mutex);
570 }
Jeff Layton3c1105d2011-05-22 07:09:13 -0400571
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400572 do {
Steve French6c3d8902006-07-31 22:46:20 +0000573 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300574
Jeff Layton73e216a2013-09-05 08:38:10 -0400575 mutex_lock(&server->srv_mutex);
Paulo Alcantaraaaa3aef2020-05-19 15:38:27 -0300576#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200577 /*
578 * Set up next DFS target server (if any) for reconnect. If DFS
579 * feature is disabled, then we will retry last server we
580 * connected to before.
581 */
Paulo Alcantara7d397a02020-07-21 09:36:40 -0300582 reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it);
Paulo Alcantaraaaa3aef2020-05-19 15:38:27 -0300583#endif
584 rc = reconn_set_ipaddr(server);
585 if (rc) {
586 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
587 __func__, rc);
588 }
589
Long Li781a8052017-11-22 17:38:36 -0700590 if (cifs_rdma_enabled(server))
591 rc = smbd_reconnect(server);
592 else
593 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000594 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500595 cifs_dbg(FYI, "reconnect error %d\n", rc);
Federico Sauter4afe2602015-03-17 17:45:28 +0100596 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700597 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 } else {
599 atomic_inc(&tcpSesReconnectCount);
Pavel Shilovsky335b7b62019-01-16 11:12:41 -0800600 set_credits(server, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000602 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000603 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000604 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100605 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400607 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500608
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200609#ifdef CONFIG_CIFS_DFS_UPCALL
610 if (tgt_it) {
611 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
612 tgt_it);
613 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000614 cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200615 __func__, rc);
616 }
617 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
618 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000619 cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200620 __func__, rc);
621 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200622 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300623
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200624 }
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300625
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -0300626 cifs_put_tcp_super(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200627#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400628 if (server->tcpStatus == CifsNeedNegotiate)
629 mod_delayed_work(cifsiod_wq, &server->echo, 0);
630
Stefan Metzmachere2e87512020-02-24 14:31:02 -0600631 wake_up(&server->response_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 return rc;
633}
634
Jeff Laytonc74093b2011-01-11 07:24:23 -0500635static void
636cifs_echo_request(struct work_struct *work)
637{
638 int rc;
639 struct TCP_Server_Info *server = container_of(work,
640 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400641 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500642
Jeff Layton247ec9b2011-02-04 17:09:50 -0500643 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400644 * If we need to renegotiate, set echo interval to zero to
645 * immediately call echo service where we can renegotiate.
646 */
647 if (server->tcpStatus == CifsNeedNegotiate)
648 echo_interval = 0;
649 else
650 echo_interval = server->echo_interval;
651
652 /*
653 * We cannot send an echo if it is disabled.
654 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500655 */
Steve French4fcd1812016-06-22 20:12:05 -0500656
657 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400658 server->tcpStatus == CifsExiting ||
659 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400660 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600661 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500662 goto requeue_echo;
663
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400664 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500665 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500666 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
667 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500668
669requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400670 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500671}
672
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400673static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400674allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400675{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400676 if (!server->bigbuf) {
677 server->bigbuf = (char *)cifs_buf_get();
678 if (!server->bigbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000679 cifs_server_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400680 msleep(3000);
681 /* retry will check if exiting */
682 return false;
683 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400684 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400685 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400686 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400687 }
688
Jeff Layton2a37ef92011-10-19 15:29:23 -0400689 if (!server->smallbuf) {
690 server->smallbuf = (char *)cifs_small_buf_get();
691 if (!server->smallbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000692 cifs_server_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400693 msleep(1000);
694 /* retry will check if exiting */
695 return false;
696 }
697 /* beginning of smb buffer is cleared in our buf_get */
698 } else {
699 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400700 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400701 }
702
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400703 return true;
704}
705
Jeff Laytonba749e62011-10-11 06:41:32 -0400706static bool
707server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400708{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300709 /*
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000710 * We need to wait 3 echo intervals to make sure we handle such
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300711 * situations right:
712 * 1s client sends a normal SMB request
Ronnie Sahlbergbecc2ba2019-07-24 11:43:49 +1000713 * 2s client gets a response
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300714 * 30s echo workqueue job pops, and decides we got a response recently
715 * and don't need to send another
716 * ...
717 * 65s kernel_recvmsg times out, and we see that we haven't gotten
718 * a response in >60s.
719 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200720 if ((server->tcpStatus == CifsGood ||
721 server->tcpStatus == CifsNeedNegotiate) &&
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000722 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000723 cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
724 (3 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400725 cifs_reconnect(server);
Jeff Laytonba749e62011-10-11 06:41:32 -0400726 return true;
727 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400728
Jeff Laytonba749e62011-10-11 06:41:32 -0400729 return false;
730}
731
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800732static inline bool
733zero_credits(struct TCP_Server_Info *server)
734{
735 int val;
736
737 spin_lock(&server->req_lock);
738 val = server->credits + server->echo_credits + server->oplock_credits;
739 if (server->in_flight == 0 && val == 0) {
740 spin_unlock(&server->req_lock);
741 return true;
742 }
743 spin_unlock(&server->req_lock);
744 return false;
745}
746
Al Viro71335662016-01-09 19:54:50 -0500747static int
748cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400749{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400750 int length = 0;
751 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400752
Al Viro71335662016-01-09 19:54:50 -0500753 smb_msg->msg_control = NULL;
754 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400755
Al Viro71335662016-01-09 19:54:50 -0500756 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500757 try_to_freeze();
758
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800759 /* reconnect if no credits and no requests in flight */
760 if (zero_credits(server)) {
761 cifs_reconnect(server);
762 return -ECONNABORTED;
763 }
764
Al Viro71335662016-01-09 19:54:50 -0500765 if (server_unresponsive(server))
766 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700767 if (cifs_rdma_enabled(server) && server->smbd_conn)
768 length = smbd_recv(server->smbd_conn, smb_msg);
769 else
770 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500771
772 if (server->tcpStatus == CifsExiting)
773 return -ESHUTDOWN;
774
775 if (server->tcpStatus == CifsNeedReconnect) {
776 cifs_reconnect(server);
777 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400778 }
779
Al Viro71335662016-01-09 19:54:50 -0500780 if (length == -ERESTARTSYS ||
781 length == -EAGAIN ||
782 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400783 /*
784 * Minimum sleep to prevent looping, allowing socket
785 * to clear and app threads to set tcpStatus
786 * CifsNeedReconnect if server hung.
787 */
788 usleep_range(1000, 2000);
789 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400790 continue;
Al Viro71335662016-01-09 19:54:50 -0500791 }
792
793 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500794 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400795 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500796 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400797 }
798 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400799 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400800}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400801
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400802int
803cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
804 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400805{
Al Viro71335662016-01-09 19:54:50 -0500806 struct msghdr smb_msg;
807 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100808 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400809
Al Viro71335662016-01-09 19:54:50 -0500810 return cifs_readv_from_socket(server, &smb_msg);
811}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400812
Al Viro71335662016-01-09 19:54:50 -0500813int
814cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700815 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500816{
817 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700818 struct bio_vec bv = {
819 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100820 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500821 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400822}
823
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400824static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400825is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400826{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400827 /*
828 * The first byte big endian of the length field,
829 * is actually not part of the length but the type
830 * with the most common, zero, as regular data.
831 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400832 switch (type) {
833 case RFC1002_SESSION_MESSAGE:
834 /* Regular SMB response */
835 return true;
836 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500837 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400838 break;
839 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500840 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400841 break;
842 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400843 /*
844 * We get this from Windows 98 instead of an error on
845 * SMB negprot response.
846 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500847 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400848 /* give server a second to clean up */
849 msleep(1000);
850 /*
851 * Always try 445 first on reconnect since we get NACK
852 * on some if we ever connected to port 139 (the NACK
853 * is since we do not begin with RFC1001 session
854 * initialize frame).
855 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400856 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400857 cifs_reconnect(server);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400858 break;
859 default:
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000860 cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400861 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400862 }
863
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400864 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400865}
866
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400867void
868dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400869{
870#ifdef CONFIG_CIFS_STATS2
871 mid->when_received = jiffies;
872#endif
873 spin_lock(&GlobalMid_Lock);
874 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400875 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400876 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400877 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000878 /*
879 * Trying to handle/dequeue a mid after the send_recv()
880 * function has finished processing it is a bug.
881 */
882 if (mid->mid_flags & MID_DELETED)
Joe Perchesa0a30362020-04-14 22:42:53 -0700883 pr_warn_once("trying to dequeue a deleted mid\n");
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700884 else {
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000885 list_del_init(&mid->qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700886 mid->mid_flags |= MID_DELETED;
887 }
Jeff Laytonea1f4502011-10-19 15:29:05 -0400888 spin_unlock(&GlobalMid_Lock);
889}
890
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800891static unsigned int
892smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
893{
894 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
895
896 /*
897 * SMB1 does not use credits.
898 */
899 if (server->vals->header_preamble_size)
900 return 0;
901
902 return le16_to_cpu(shdr->CreditRequest);
903}
904
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400905static void
906handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400907 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400908{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400909 if (server->ops->check_trans2 &&
910 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400911 return;
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800912 mid->credits_received = smb2_get_credits_from_hdr(buf, server);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400913 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400914 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400915 /* Was previous buf put in mpx struct for multi-rsp? */
916 if (!mid->multiRsp) {
917 /* smb buffer will be freed by user thread */
918 if (server->large_buf)
919 server->bigbuf = NULL;
920 else
921 server->smallbuf = NULL;
922 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400923 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400924}
925
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400926static void clean_demultiplex_info(struct TCP_Server_Info *server)
927{
928 int length;
929
930 /* take it off the list, if it's not already */
931 spin_lock(&cifs_tcp_ses_lock);
932 list_del_init(&server->tcp_ses_list);
933 spin_unlock(&cifs_tcp_ses_lock);
934
935 spin_lock(&GlobalMid_Lock);
936 server->tcpStatus = CifsExiting;
937 spin_unlock(&GlobalMid_Lock);
938 wake_up_all(&server->response_q);
939
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400940 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300941 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400942 if (server->credits <= 0)
943 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300944 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400945 /*
946 * Although there should not be any requests blocked on this queue it
947 * can not hurt to be paranoid and try to wake up requests that may
948 * haven been blocked when more than 50 at time were on the wire to the
949 * same server - they now will see the session is in exit state and get
950 * out of SendReceive.
951 */
952 wake_up_all(&server->request_q);
953 /* give those requests time to exit */
954 msleep(125);
Long Li050b8c32019-04-04 11:35:42 -0500955 if (cifs_rdma_enabled(server))
956 smbd_destroy(server);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400957 if (server->ssocket) {
958 sock_release(server->ssocket);
959 server->ssocket = NULL;
960 }
961
962 if (!list_empty(&server->pending_mid_q)) {
963 struct list_head dispose_list;
964 struct mid_q_entry *mid_entry;
965 struct list_head *tmp, *tmp2;
966
967 INIT_LIST_HEAD(&dispose_list);
968 spin_lock(&GlobalMid_Lock);
969 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
970 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500971 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700972 kref_get(&mid_entry->refcount);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400973 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400974 list_move(&mid_entry->qhead, &dispose_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700975 mid_entry->mid_flags |= MID_DELETED;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400976 }
977 spin_unlock(&GlobalMid_Lock);
978
979 /* now walk dispose list and issue callbacks */
980 list_for_each_safe(tmp, tmp2, &dispose_list) {
981 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500982 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400983 list_del_init(&mid_entry->qhead);
984 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700985 cifs_mid_q_entry_release(mid_entry);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400986 }
987 /* 1/8th of sec is more than enough time for them to exit */
988 msleep(125);
989 }
990
991 if (!list_empty(&server->pending_mid_q)) {
992 /*
993 * mpx threads have not exited yet give them at least the smb
994 * send timeout time for long ops.
995 *
996 * Due to delays on oplock break requests, we need to wait at
997 * least 45 seconds before giving up on a request getting a
998 * response and going ahead and killing cifsd.
999 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001000 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001001 msleep(46000);
1002 /*
1003 * If threads still have not exited they are probably never
1004 * coming home not much else we can do but free the memory.
1005 */
1006 }
1007
1008 kfree(server->hostname);
1009 kfree(server);
1010
1011 length = atomic_dec_return(&tcpSesAllocCount);
1012 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -07001013 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001014}
1015
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001016static int
Jeff Laytone9097ab2011-10-19 15:29:40 -04001017standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1018{
1019 int length;
1020 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +10001021 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001022
1023 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001024 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
1025 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001026 cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001027 cifs_reconnect(server);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +04001028 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001029 }
1030
1031 /* switch to large buffer if too big for a small one */
1032 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
1033 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001034 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001035 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001036 }
1037
1038 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001039 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001040 pdu_length - HEADER_SIZE(server) + 1
1041 + server->vals->header_preamble_size);
1042
Jeff Laytone9097ab2011-10-19 15:29:40 -04001043 if (length < 0)
1044 return length;
1045 server->total_read += length;
1046
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001047 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001048
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08001049 return cifs_handle_standard(server, mid);
1050}
1051
1052int
1053cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1054{
1055 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1056 int length;
1057
Jeff Laytone9097ab2011-10-19 15:29:40 -04001058 /*
1059 * We know that we received enough to get to the MID as we
1060 * checked the pdu_length earlier. Now check to see
1061 * if the rest of the header is OK. We borrow the length
1062 * var for the rest of the loop to avoid a new stack var.
1063 *
1064 * 48 bytes is enough to display the header and a little bit
1065 * into the payload for debugging purposes.
1066 */
Steve French373512e2015-12-18 13:05:30 -06001067 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001068 if (length != 0)
1069 cifs_dump_mem("Bad SMB: ", buf,
1070 min_t(unsigned int, server->total_read, 48));
1071
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001072 if (server->ops->is_session_expired &&
1073 server->ops->is_session_expired(buf)) {
1074 cifs_reconnect(server);
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001075 return -1;
1076 }
1077
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001078 if (server->ops->is_status_pending &&
Pavel Shilovsky66265f12019-01-23 17:11:16 -08001079 server->ops->is_status_pending(buf, server))
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001080 return -1;
1081
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001082 if (!mid)
1083 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001084
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001085 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001086 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001087}
1088
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001089static void
1090smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
1091{
1092 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
1093
1094 /*
1095 * SMB1 does not use credits.
1096 */
1097 if (server->vals->header_preamble_size)
1098 return;
1099
1100 if (shdr->CreditRequest) {
1101 spin_lock(&server->req_lock);
1102 server->credits += le16_to_cpu(shdr->CreditRequest);
1103 spin_unlock(&server->req_lock);
1104 wake_up(&server->request_q);
1105 }
1106}
1107
1108
Jeff Laytone9097ab2011-10-19 15:29:40 -04001109static int
Al Viro7c97c202011-06-21 08:51:28 -04001110cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001112 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001113 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001114 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001115 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001116 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001117 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001118 struct mid_q_entry *mids[MAX_COMPOUND];
1119 char *bufs[MAX_COMPOUND];
Eric Biggersdc920272020-03-08 22:58:20 -07001120 unsigned int noreclaim_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
Eric Biggersdc920272020-03-08 22:58:20 -07001122 noreclaim_flag = memalloc_noreclaim_save();
Joe Perchesf96637b2013-05-04 22:12:25 -05001123 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001124
1125 length = atomic_inc_return(&tcpSesAllocCount);
1126 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001127 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001129 set_freezable();
Eric W. Biederman33da8e72019-08-16 12:33:54 -05001130 allow_kernel_signal(SIGKILL);
Jeff Layton469ee612008-10-16 18:46:39 +00001131 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001132 if (try_to_freeze())
1133 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001134
Jeff Layton2a37ef92011-10-19 15:29:23 -04001135 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001136 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001137
Jeff Layton2a37ef92011-10-19 15:29:23 -04001138 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001139 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001140 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001141
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001142 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001143 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001144 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001145
1146 if (server->vals->header_preamble_size == 0)
1147 server->total_read = 0;
1148 else
1149 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001150
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001151 /*
1152 * The right amount was read from socket - 4 bytes,
1153 * so we can now interpret the length field.
1154 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001155 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001156
Joe Perchesf96637b2013-05-04 22:12:25 -05001157 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001158 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001159 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001160next_pdu:
1161 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001162
Jeff Layton89482a52011-10-19 15:28:57 -04001163 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001164 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001165 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001166 cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001167 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001168 cifs_reconnect(server);
Jeff Layton89482a52011-10-19 15:28:57 -04001169 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001170 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001171
Jeff Layton89482a52011-10-19 15:28:57 -04001172 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001173 length = cifs_read_from_socket(server,
1174 buf + server->vals->header_preamble_size,
1175 HEADER_SIZE(server) - 1
1176 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001177 if (length < 0)
1178 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001179 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001180
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001181 if (server->ops->next_header) {
1182 next_offset = server->ops->next_header(buf);
1183 if (next_offset)
1184 server->pdu_size = next_offset;
1185 }
1186
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001187 memset(mids, 0, sizeof(mids));
1188 memset(bufs, 0, sizeof(bufs));
1189 num_mids = 0;
1190
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001191 if (server->ops->is_transform_hdr &&
1192 server->ops->receive_transform &&
1193 server->ops->is_transform_hdr(buf)) {
1194 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001195 mids,
1196 bufs,
1197 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001198 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001199 mids[0] = server->ops->find_mid(server, buf);
1200 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001201 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001202
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001203 if (!mids[0] || !mids[0]->receive)
1204 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001205 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001206 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001207 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001208
Lars Persson696e4202018-06-25 14:05:25 +02001209 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001210 for (i = 0; i < num_mids; i++)
1211 if (mids[i])
1212 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001213 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001214 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001215
Steve Frenchfda35942011-01-20 18:06:34 +00001216 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001217
1218 for (i = 0; i < num_mids; i++) {
1219 if (mids[i] != NULL) {
1220 mids[i]->resp_buf_size = server->pdu_size;
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001221
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001222 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1223 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001224
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001225 cifs_mid_q_entry_release(mids[i]);
1226 } else if (server->ops->is_oplock_break &&
1227 server->ops->is_oplock_break(bufs[i],
1228 server)) {
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001229 smb2_add_credits_from_hdr(bufs[i], server);
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001230 cifs_dbg(FYI, "Received oplock break\n");
1231 } else {
Joe Perchesa0a30362020-04-14 22:42:53 -07001232 cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
1233 atomic_read(&midCount));
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001234 cifs_dump_mem("Received Data is: ", bufs[i],
1235 HEADER_SIZE(server));
Ronnie Sahlberg3e272572019-07-06 06:43:08 +10001236 smb2_add_credits_from_hdr(bufs[i], server);
Steve French39798772006-05-31 22:40:51 +00001237#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001238 if (server->ops->dump_detail)
1239 server->ops->dump_detail(bufs[i],
1240 server);
1241 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001242#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001243 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001244 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001245
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001246 if (pdu_length > server->pdu_size) {
1247 if (!allocate_buffers(server))
1248 continue;
1249 pdu_length -= server->pdu_size;
1250 server->total_read = 0;
1251 server->large_buf = false;
1252 buf = server->smallbuf;
1253 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001254 }
1255 } /* end while !EXITING */
1256
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001257 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001258 cifs_buf_release(server->bigbuf);
1259 if (server->smallbuf) /* no sense logging a debug message if NULL */
1260 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001262 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001263 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001264
1265 /* if server->tsk was NULL then wait for a signal before exiting */
1266 if (!task_to_wake) {
1267 set_current_state(TASK_INTERRUPTIBLE);
1268 while (!signal_pending(current)) {
1269 schedule();
1270 set_current_state(TASK_INTERRUPTIBLE);
1271 }
1272 set_current_state(TASK_RUNNING);
1273 }
1274
Eric Biggersdc920272020-03-08 22:58:20 -07001275 memalloc_noreclaim_restore(noreclaim_flag);
Jeff Layton0468a2c2008-12-01 07:09:35 -05001276 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277}
1278
Jeff Laytonc359cf32007-11-16 22:22:06 +00001279/* extract the host portion of the UNC string */
1280static char *
1281extract_hostname(const char *unc)
1282{
1283 const char *src;
1284 char *dst, *delim;
1285 unsigned int len;
1286
1287 /* skip double chars at beginning of string */
1288 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001289 if (strlen(unc) < 3)
1290 return ERR_PTR(-EINVAL);
1291 for (src = unc; *src && *src == '\\'; src++)
1292 ;
1293 if (!*src)
1294 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001295
1296 /* delimiter between hostname and sharename is always '\\' now */
1297 delim = strchr(src, '\\');
1298 if (!delim)
1299 return ERR_PTR(-EINVAL);
1300
1301 len = delim - src;
1302 dst = kmalloc((len + 1), GFP_KERNEL);
1303 if (dst == NULL)
1304 return ERR_PTR(-ENOMEM);
1305
1306 memcpy(dst, src, len);
1307 dst[len] = '\0';
1308
1309 return dst;
1310}
1311
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001312static int get_option_ul(substring_t args[], unsigned long *option)
1313{
1314 int rc;
1315 char *string;
1316
1317 string = match_strdup(args);
1318 if (string == NULL)
1319 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001320 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001321 kfree(string);
1322
1323 return rc;
1324}
1325
Eric W. Biederman3da46562013-02-06 01:37:39 -08001326static int get_option_uid(substring_t args[], kuid_t *result)
1327{
1328 unsigned long value;
1329 kuid_t uid;
1330 int rc;
1331
1332 rc = get_option_ul(args, &value);
1333 if (rc)
1334 return rc;
1335
1336 uid = make_kuid(current_user_ns(), value);
1337 if (!uid_valid(uid))
1338 return -EINVAL;
1339
1340 *result = uid;
1341 return 0;
1342}
1343
1344static int get_option_gid(substring_t args[], kgid_t *result)
1345{
1346 unsigned long value;
1347 kgid_t gid;
1348 int rc;
1349
1350 rc = get_option_ul(args, &value);
1351 if (rc)
1352 return rc;
1353
1354 gid = make_kgid(current_user_ns(), value);
1355 if (!gid_valid(gid))
1356 return -EINVAL;
1357
1358 *result = gid;
1359 return 0;
1360}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001361
1362static int cifs_parse_security_flavors(char *value,
1363 struct smb_vol *vol)
1364{
1365
1366 substring_t args[MAX_OPT_ARGS];
1367
Jeff Layton1e3cc572013-06-10 17:12:23 -05001368 /*
1369 * With mount options, the last one should win. Reset any existing
1370 * settings back to default.
1371 */
1372 vol->sectype = Unspecified;
1373 vol->sign = false;
1374
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001375 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001376 case Opt_sec_krb5p:
1377 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1378 return 1;
1379 case Opt_sec_krb5i:
1380 vol->sign = true;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001381 fallthrough;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001382 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001383 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001384 break;
1385 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001386 vol->sign = true;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001387 fallthrough;
Jeff Layton3f618222013-06-12 19:52:14 -05001388 case Opt_sec_ntlmssp:
1389 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001390 break;
1391 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001392 vol->sign = true;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001393 fallthrough;
Jeff Layton3f618222013-06-12 19:52:14 -05001394 case Opt_ntlm:
1395 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001396 break;
1397 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001398 vol->sign = true;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001399 fallthrough;
Jeff Layton3f618222013-06-12 19:52:14 -05001400 case Opt_sec_ntlmv2:
1401 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001402 break;
1403#ifdef CONFIG_CIFS_WEAK_PW_HASH
1404 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001405 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001406 break;
1407#endif
1408 case Opt_sec_none:
1409 vol->nullauth = 1;
1410 break;
1411 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001412 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001413 return 1;
1414 }
1415
1416 return 0;
1417}
1418
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001420cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1421{
1422 substring_t args[MAX_OPT_ARGS];
1423
1424 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1425 case Opt_cache_loose:
1426 vol->direct_io = false;
1427 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001428 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001429 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001430 break;
1431 case Opt_cache_strict:
1432 vol->direct_io = false;
1433 vol->strict_io = true;
Steve French83bbfa72019-08-27 23:58:54 -05001434 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001435 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001436 break;
1437 case Opt_cache_none:
1438 vol->direct_io = true;
1439 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001440 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001441 vol->cache_rw = false;
Steve French83bbfa72019-08-27 23:58:54 -05001442 break;
1443 case Opt_cache_ro:
1444 vol->direct_io = false;
1445 vol->strict_io = false;
1446 vol->cache_ro = true;
Steve French41e033f2019-08-30 02:12:41 -05001447 vol->cache_rw = false;
1448 break;
1449 case Opt_cache_rw:
1450 vol->direct_io = false;
1451 vol->strict_io = false;
1452 vol->cache_ro = false;
1453 vol->cache_rw = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001454 break;
1455 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001456 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001457 return 1;
1458 }
1459 return 0;
1460}
1461
1462static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001463cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001464{
1465 substring_t args[MAX_OPT_ARGS];
1466
1467 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001468#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001469 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001470 if (disable_legacy_dialects) {
1471 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1472 return 1;
1473 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001474 if (is_smb3) {
1475 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1476 return 1;
1477 }
Joe Perchesa0a30362020-04-14 22:42:53 -07001478 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 -04001479 vol->ops = &smb1_operations;
1480 vol->vals = &smb1_values;
1481 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001482 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001483 if (disable_legacy_dialects) {
1484 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1485 return 1;
1486 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001487 if (is_smb3) {
1488 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1489 return 1;
1490 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001491 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001492 vol->vals = &smb20_values;
1493 break;
Steve French74204512018-06-19 14:34:08 -05001494#else
1495 case Smb_1:
1496 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1497 return 1;
1498 case Smb_20:
1499 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1500 return 1;
1501#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001502 case Smb_21:
1503 vol->ops = &smb21_operations;
1504 vol->vals = &smb21_values;
1505 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001506 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001507 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001508 vol->vals = &smb30_values;
1509 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001510 case Smb_302:
1511 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1512 vol->vals = &smb302_values;
1513 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001514 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001515 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001516 vol->vals = &smb311_values;
1517 break;
Steve French9764c022017-09-17 10:41:35 -05001518 case Smb_3any:
1519 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1520 vol->vals = &smb3any_values;
1521 break;
1522 case Smb_default:
1523 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1524 vol->vals = &smbdefault_values;
1525 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001526 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001527 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001528 return 1;
1529 }
1530 return 0;
1531}
1532
Jeff Laytond387a5c2012-12-10 06:10:46 -05001533/*
1534 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1535 * fields with the result. Returns 0 on success and an error otherwise.
1536 */
1537static int
1538cifs_parse_devname(const char *devname, struct smb_vol *vol)
1539{
1540 char *pos;
1541 const char *delims = "/\\";
1542 size_t len;
1543
Yao Liu68e26722019-01-28 19:47:28 +08001544 if (unlikely(!devname || !*devname)) {
Joe Perchesa0a30362020-04-14 22:42:53 -07001545 cifs_dbg(VFS, "Device name not specified\n");
Yao Liu68e26722019-01-28 19:47:28 +08001546 return -EINVAL;
1547 }
1548
Jeff Laytond387a5c2012-12-10 06:10:46 -05001549 /* make sure we have a valid UNC double delimiter prefix */
1550 len = strspn(devname, delims);
1551 if (len != 2)
1552 return -EINVAL;
1553
1554 /* find delimiter between host and sharename */
1555 pos = strpbrk(devname + 2, delims);
1556 if (!pos)
1557 return -EINVAL;
1558
1559 /* skip past delimiter */
1560 ++pos;
1561
1562 /* now go until next delimiter or end of string */
1563 len = strcspn(pos, delims);
1564
1565 /* move "pos" up to delimiter or NULL */
1566 pos += len;
1567 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1568 if (!vol->UNC)
1569 return -ENOMEM;
1570
1571 convert_delimiter(vol->UNC, '\\');
1572
Sachin Prabhu11e31642016-02-08 13:44:01 +05301573 /* skip any delimiter */
1574 if (*pos == '/' || *pos == '\\')
1575 pos++;
1576
1577 /* If pos is NULL then no prepath */
1578 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001579 return 0;
1580
1581 vol->prepath = kstrdup(pos, GFP_KERNEL);
1582 if (!vol->prepath)
1583 return -ENOMEM;
1584
1585 return 0;
1586}
1587
Jeff Layton23db65f2012-05-15 12:20:51 -04001588static int
Sean Finneyb9468452011-04-11 13:19:32 +00001589cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001590 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001592 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001593 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 unsigned int temp_len, i, j;
1595 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001596 short int override_uid = -1;
1597 short int override_gid = -1;
1598 bool uid_specified = false;
1599 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001600 bool sloppy = false;
1601 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001602 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001603 char *string = NULL;
1604 char *tmp_end, *value;
1605 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001606 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001607 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001608 unsigned short port = 0;
1609 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610
1611 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001612 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001613 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614
Jeff Layton6ee95422012-11-26 11:09:57 -05001615 /* ensure we always start with zeroed-out smb_vol */
1616 memset(vol, 0, sizeof(*vol));
1617
Jeff Layton88463992010-11-22 15:31:03 -05001618 /*
1619 * does not have to be perfect mapping since field is
1620 * informational, only used for servers that do not support
1621 * port 445 and it can be overridden at mount time
1622 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001623 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1624 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001625 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1626
Jeff Layton1397f2e2011-01-07 11:30:28 -05001627 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001628 /* null target name indicates to use *SMBSERVR default called name
1629 if we end up sending RFC1001 session initialize */
1630 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001631 vol->cred_uid = current_uid();
1632 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001633 vol->linux_gid = current_gid();
Steve Frenche8506d22019-02-28 21:32:15 -06001634 vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
Steve French2baa2682014-09-27 02:19:01 -05001635 /*
1636 * default to SFM style remapping of seven reserved characters
1637 * unless user overrides it or we negotiate CIFS POSIX where
1638 * it is unnecessary. Can not simultaneously use more than one mapping
1639 * since then readdir could list files that open could not open
1640 */
1641 vol->remap = true;
1642
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001643 /* default to only allowing write access to owner of the mount */
1644 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
1646 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001647 /* default is always to request posix paths. */
1648 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001649 /* default to using server inode numbers where available */
1650 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001651
Jeff Layton1b359202012-09-19 15:20:27 -07001652 /* default is to use strict cifs caching semantics */
1653 vol->strict_io = true;
1654
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301655 vol->actimeo = CIFS_DEF_ACTIMEO;
1656
Steve Frenchca567eb2019-03-29 16:31:07 -05001657 /* Most clients set timeout to 0, allows server to use its default */
1658 vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1659
Steve French9764c022017-09-17 10:41:35 -05001660 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1661 vol->ops = &smb30_operations;
1662 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001663
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001664 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1665
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001666 /* default to no multichannel (single server connection) */
1667 vol->multichannel = false;
1668 vol->max_channels = 1;
1669
Sean Finneyb9468452011-04-11 13:19:32 +00001670 if (!mountdata)
1671 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672
Sean Finneyb9468452011-04-11 13:19:32 +00001673 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1674 if (!mountdata_copy)
1675 goto cifs_parse_mount_err;
1676
1677 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001678 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001679
Steve French50c2f752007-07-13 00:33:32 +00001680 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001681 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 separator[0] = options[4];
1683 options += 5;
1684 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001685 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 }
1687 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001688 vol->backupuid_specified = false; /* no backup intent for a user */
1689 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001690
Jeff Layton37d4f992013-05-24 07:40:05 -04001691 switch (cifs_parse_devname(devname, vol)) {
1692 case 0:
1693 break;
1694 case -ENOMEM:
Joe Perchesa0a30362020-04-14 22:42:53 -07001695 cifs_dbg(VFS, "Unable to allocate memory for devname\n");
Jeff Layton37d4f992013-05-24 07:40:05 -04001696 goto cifs_parse_mount_err;
1697 case -EINVAL:
Joe Perchesa0a30362020-04-14 22:42:53 -07001698 cifs_dbg(VFS, "Malformed UNC in devname\n");
Jeff Layton37d4f992013-05-24 07:40:05 -04001699 goto cifs_parse_mount_err;
1700 default:
Joe Perchesa0a30362020-04-14 22:42:53 -07001701 cifs_dbg(VFS, "Unknown error parsing devname\n");
Jeff Layton37d4f992013-05-24 07:40:05 -04001702 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001703 }
1704
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001706 substring_t args[MAX_OPT_ARGS];
1707 unsigned long option;
1708 int token;
1709
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 if (!*data)
1711 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001713 token = match_token(data, cifs_mount_option_tokens, args);
1714
1715 switch (token) {
1716
1717 /* Ingnore the following */
1718 case Opt_ignore:
1719 break;
1720
1721 /* Boolean values */
1722 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001724 break;
1725 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001727 break;
1728 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001729 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001730 break;
1731 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001732 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001733 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001734 case Opt_forcegid:
1735 override_gid = 1;
1736 break;
1737 case Opt_noforcegid:
1738 override_gid = 0;
1739 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001740 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001741 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001742 break;
1743 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001744 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 break;
Steve French3e7a02d2019-09-11 21:46:20 -05001746 case Opt_nolease:
1747 vol->no_lease = 1;
1748 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001749 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001751 break;
1752 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001754 break;
1755 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001757 break;
1758 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001760 break;
Steve French82e93672020-05-19 03:06:57 -05001761 case Opt_nodelete:
1762 vol->nodelete = 1;
1763 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001764 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001765 vol->sfu_remap = true;
1766 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001767 break;
1768 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001769 vol->sfu_remap = false;
1770 break;
1771 case Opt_mapposix:
1772 vol->remap = true;
1773 vol->sfu_remap = false; /* disable SFU mapping */
1774 break;
1775 case Opt_nomapposix:
1776 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001777 break;
1778 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001779 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001780 break;
1781 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001782 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001783 break;
1784 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001785 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001786 break;
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03001787 case Opt_rootfs:
1788#ifdef CONFIG_CIFS_ROOT
1789 vol->rootfs = true;
1790#endif
1791 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001792 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001793 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001794 break;
1795 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001796 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001797 break;
1798 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001799 if (vol->linux_ext)
1800 cifs_dbg(VFS,
1801 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001802 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001804 case Opt_unix:
1805 if (vol->no_linux_ext)
1806 cifs_dbg(VFS,
1807 "conflicting unix mount options\n");
1808 vol->linux_ext = 1;
1809 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001810 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001811 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001812 break;
1813 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001814 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001815 break;
1816 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001817 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001818 /*
1819 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001820 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001821 * local vfs will do advisory
1822 */
Steve French50c2f752007-07-13 00:33:32 +00001823 if (vol->file_mode ==
1824 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001825 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001826 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001827 case Opt_nohandlecache:
1828 vol->nohandlecache = 1;
1829 break;
1830 case Opt_handlecache:
1831 vol->nohandlecache = 0;
1832 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001833 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001834 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001835 break;
1836 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001838 break;
1839 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001841 break;
Steve French95932652016-09-23 01:36:34 -05001842 case Opt_setuidfromacl:
1843 vol->setuidfromacl = 1;
1844 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001845 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001846 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001847 break;
1848 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001849 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001850 break;
1851 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001853 break;
1854 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001856 break;
1857 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001859 break;
1860 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001862 break;
1863 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001864 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001865 break;
1866 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001867 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001868 break;
1869 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001871 break;
1872 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001874 break;
1875 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001876 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001877 break;
Steve French412094a2019-06-24 02:01:42 -05001878 case Opt_modesid:
1879 vol->mode_ace = 1;
1880 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001881 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001882 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001883 break;
1884 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001885 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001886 break;
1887 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001889 break;
1890 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001892 break;
1893 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001894 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001895 break;
1896 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001897 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001898 break;
Steve French4f5c10f2019-09-03 21:18:49 -05001899 case Opt_ignore_signature:
1900 vol->sign = true;
1901 vol->ignore_signature = true;
1902 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001903 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001904 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001905 * is a per tree connection (mount) not a per socket
1906 * or per-smb connection option in the protocol
1907 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1908 */
Steve French95b1cb92008-05-15 16:44:38 +00001909 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001910 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001911 case Opt_noac:
Joe Perchesa0a30362020-04-14 22:42:53 -07001912 pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001913 break;
1914 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301915#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001916 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001917 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301918#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301919 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001920 break;
1921 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001922 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001923 break;
1924 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001925 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001926 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001927 case Opt_sloppy:
1928 sloppy = true;
1929 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001930 case Opt_nosharesock:
1931 vol->nosharesock = true;
1932 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001933 case Opt_nopersistent:
1934 vol->nopersistent = true;
1935 if (vol->persistent) {
1936 cifs_dbg(VFS,
1937 "persistenthandles mount options conflict\n");
1938 goto cifs_parse_mount_err;
1939 }
1940 break;
1941 case Opt_persistent:
1942 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001943 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001944 cifs_dbg(VFS,
1945 "persistenthandles mount options conflict\n");
1946 goto cifs_parse_mount_err;
1947 }
1948 break;
Steve French592fafe2015-11-03 10:08:53 -06001949 case Opt_resilient:
1950 vol->resilient = true;
1951 if (vol->persistent) {
1952 cifs_dbg(VFS,
1953 "persistenthandles mount options conflict\n");
1954 goto cifs_parse_mount_err;
1955 }
1956 break;
1957 case Opt_noresilient:
1958 vol->resilient = false; /* already the default */
1959 break;
Germano Percossi39566442016-12-15 12:31:18 +05301960 case Opt_domainauto:
1961 vol->domainauto = true;
1962 break;
Long Li8339dd32017-11-07 01:54:55 -07001963 case Opt_rdma:
1964 vol->rdma = true;
1965 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001966 case Opt_multichannel:
1967 vol->multichannel = true;
Steve French1ee0e6d2020-06-02 23:17:16 -05001968 /* if number of channels not specified, default to 2 */
1969 if (vol->max_channels < 2)
1970 vol->max_channels = 2;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001971 break;
1972 case Opt_nomultichannel:
1973 vol->multichannel = false;
Steve French1ee0e6d2020-06-02 23:17:16 -05001974 vol->max_channels = 1;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001975 break;
Steve French9fe5ff12019-06-24 20:39:04 -05001976 case Opt_compress:
1977 vol->compression = UNKNOWN_TYPE;
1978 cifs_dbg(VFS,
1979 "SMB3 compression support is experimental\n");
1980 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001981
1982 /* Numeric Values */
1983 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001984 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001985 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1986 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001987 goto cifs_parse_mount_err;
1988 }
1989 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001990 break;
1991 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001992 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001993 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1994 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001995 goto cifs_parse_mount_err;
1996 }
1997 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001998 break;
1999 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002000 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002001 cifs_dbg(VFS, "%s: Invalid uid value\n",
2002 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00002003 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002005 uid_specified = true;
2006 break;
2007 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002008 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002009 cifs_dbg(VFS, "%s: Invalid cruid value\n",
2010 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002011 goto cifs_parse_mount_err;
2012 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002013 break;
2014 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002015 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002016 cifs_dbg(VFS, "%s: Invalid gid value\n",
2017 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002018 goto cifs_parse_mount_err;
2019 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002020 gid_specified = true;
2021 break;
2022 case Opt_file_mode:
2023 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002024 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
2025 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002026 goto cifs_parse_mount_err;
2027 }
2028 vol->file_mode = option;
2029 break;
2030 case Opt_dirmode:
2031 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002032 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
2033 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002034 goto cifs_parse_mount_err;
2035 }
2036 vol->dir_mode = option;
2037 break;
2038 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002039 if (get_option_ul(args, &option) ||
2040 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002041 cifs_dbg(VFS, "%s: Invalid port value\n",
2042 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002043 goto cifs_parse_mount_err;
2044 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002045 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002046 break;
Steve French563317e2019-09-08 23:22:02 -05002047 case Opt_min_enc_offload:
2048 if (get_option_ul(args, &option)) {
2049 cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
2050 goto cifs_parse_mount_err;
2051 }
2052 vol->min_offload = option;
2053 break;
Steve Frenche8506d22019-02-28 21:32:15 -06002054 case Opt_blocksize:
2055 if (get_option_ul(args, &option)) {
2056 cifs_dbg(VFS, "%s: Invalid blocksize value\n",
2057 __func__);
2058 goto cifs_parse_mount_err;
2059 }
2060 /*
2061 * inode blocksize realistically should never need to be
2062 * less than 16K or greater than 16M and default is 1MB.
2063 * Note that small inode block sizes (e.g. 64K) can lead
2064 * to very poor performance of common tools like cp and scp
2065 */
2066 if ((option < CIFS_MAX_MSGSIZE) ||
2067 (option > (4 * SMB3_DEFAULT_IOSIZE))) {
2068 cifs_dbg(VFS, "%s: Invalid blocksize\n",
2069 __func__);
2070 goto cifs_parse_mount_err;
2071 }
2072 vol->bsize = option;
2073 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002074 case Opt_rsize:
2075 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002076 cifs_dbg(VFS, "%s: Invalid rsize value\n",
2077 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002078 goto cifs_parse_mount_err;
2079 }
2080 vol->rsize = option;
2081 break;
2082 case Opt_wsize:
2083 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002084 cifs_dbg(VFS, "%s: Invalid wsize value\n",
2085 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002086 goto cifs_parse_mount_err;
2087 }
2088 vol->wsize = option;
2089 break;
2090 case Opt_actimeo:
2091 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002092 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
2093 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002094 goto cifs_parse_mount_err;
2095 }
2096 vol->actimeo = HZ * option;
2097 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002098 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002099 goto cifs_parse_mount_err;
2100 }
2101 break;
Steve Frenchca567eb2019-03-29 16:31:07 -05002102 case Opt_handletimeout:
2103 if (get_option_ul(args, &option)) {
2104 cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
2105 __func__);
2106 goto cifs_parse_mount_err;
2107 }
2108 vol->handle_timeout = option;
2109 if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
2110 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
2111 goto cifs_parse_mount_err;
2112 }
2113 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002114 case Opt_echo_interval:
2115 if (get_option_ul(args, &option)) {
2116 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
2117 __func__);
2118 goto cifs_parse_mount_err;
2119 }
2120 vol->echo_interval = option;
2121 break;
Steve French8b217fe2016-11-11 22:36:20 -06002122 case Opt_snapshot:
2123 if (get_option_ul(args, &option)) {
2124 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
2125 __func__);
2126 goto cifs_parse_mount_err;
2127 }
2128 vol->snapshot_time = option;
2129 break;
Steve French141891f2016-09-23 00:44:16 -05002130 case Opt_max_credits:
2131 if (get_option_ul(args, &option) || (option < 20) ||
2132 (option > 60000)) {
2133 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
2134 __func__);
2135 goto cifs_parse_mount_err;
2136 }
2137 vol->max_credits = option;
2138 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002139 case Opt_max_channels:
2140 if (get_option_ul(args, &option) || option < 1 ||
2141 option > CIFS_MAX_CHANNELS) {
2142 cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
2143 __func__, CIFS_MAX_CHANNELS);
2144 goto cifs_parse_mount_err;
2145 }
2146 vol->max_channels = option;
2147 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002148
2149 /* String Arguments */
2150
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002151 case Opt_blank_user:
2152 /* null user, ie. anonymous authentication */
2153 vol->nullauth = 1;
2154 vol->username = NULL;
2155 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002156 case Opt_user:
2157 string = match_strdup(args);
2158 if (string == NULL)
2159 goto out_nomem;
2160
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002161 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
2162 CIFS_MAX_USERNAME_LEN) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002163 pr_warn("username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002164 goto cifs_parse_mount_err;
2165 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002166
2167 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002168 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05002169 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002170 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002171 break;
2172 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002173 /* passwords have to be handled differently
2174 * to allow the character used for deliminator
2175 * to be passed within them
2176 */
2177
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002178 /*
2179 * Check if this is a case where the password
2180 * starts with a delimiter
2181 */
2182 tmp_end = strchr(data, '=');
2183 tmp_end++;
2184 if (!(tmp_end < end && tmp_end[1] == delim)) {
2185 /* No it is not. Set the password to NULL */
Waiman Long453431a2020-08-06 23:18:13 -07002186 kfree_sensitive(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002187 vol->password = NULL;
2188 break;
2189 }
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05002190 fallthrough; /* to Opt_pass below */
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002191 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002192 /* Obtain the value string */
2193 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002194 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002195
2196 /* Set tmp_end to end of the string */
2197 tmp_end = (char *) value + strlen(value);
2198
2199 /* Check if following character is the deliminator
2200 * If yes, we have encountered a double deliminator
2201 * reset the NULL character to the deliminator
2202 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302203 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002204 tmp_end[0] = delim;
2205
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302206 /* Keep iterating until we get to a single
2207 * deliminator OR the end
2208 */
2209 while ((tmp_end = strchr(tmp_end, delim))
2210 != NULL && (tmp_end[1] == delim)) {
2211 tmp_end = (char *) &tmp_end[2];
2212 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002213
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302214 /* Reset var options to point to next element */
2215 if (tmp_end) {
2216 tmp_end[0] = '\0';
2217 options = (char *) &tmp_end[1];
2218 } else
2219 /* Reached the end of the mount option
2220 * string */
2221 options = end;
2222 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002223
Waiman Long453431a2020-08-06 23:18:13 -07002224 kfree_sensitive(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002225 /* Now build new password string */
2226 temp_len = strlen(value);
2227 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2228 if (vol->password == NULL) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002229 pr_warn("no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002230 goto cifs_parse_mount_err;
2231 }
2232
2233 for (i = 0, j = 0; i < temp_len; i++, j++) {
2234 vol->password[j] = value[i];
2235 if ((value[i] == delim) &&
2236 value[i+1] == delim)
2237 /* skip the second deliminator */
2238 i++;
2239 }
2240 vol->password[j] = '\0';
2241 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002242 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002243 /* FIXME: should this be an error instead? */
2244 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002245 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002246 case Opt_ip:
2247 string = match_strdup(args);
2248 if (string == NULL)
2249 goto out_nomem;
2250
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002251 if (!cifs_convert_address(dstaddr, string,
2252 strlen(string))) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002253 pr_err("bad ip= option (%s)\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002254 goto cifs_parse_mount_err;
2255 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002256 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002257 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002258 case Opt_domain:
2259 string = match_strdup(args);
2260 if (string == NULL)
2261 goto out_nomem;
2262
Chen Gang057d6332013-07-19 09:01:36 +08002263 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2264 == CIFS_MAX_DOMAINNAME_LEN) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002265 pr_warn("domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002266 goto cifs_parse_mount_err;
2267 }
2268
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002269 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002270 vol->domainname = kstrdup(string, GFP_KERNEL);
2271 if (!vol->domainname) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002272 pr_warn("no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002273 goto cifs_parse_mount_err;
2274 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002275 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002276 break;
2277 case Opt_srcaddr:
2278 string = match_strdup(args);
2279 if (string == NULL)
2280 goto out_nomem;
2281
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002282 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002283 (struct sockaddr *)&vol->srcaddr,
2284 string, strlen(string))) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002285 pr_warn("Could not parse srcaddr: %s\n",
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002286 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002287 goto cifs_parse_mount_err;
2288 }
2289 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002290 case Opt_iocharset:
2291 string = match_strdup(args);
2292 if (string == NULL)
2293 goto out_nomem;
2294
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002295 if (strnlen(string, 1024) >= 65) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002296 pr_warn("iocharset name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002297 goto cifs_parse_mount_err;
2298 }
2299
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002300 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002301 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002302 vol->iocharset = kstrdup(string,
2303 GFP_KERNEL);
2304 if (!vol->iocharset) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002305 pr_warn("no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002306 goto cifs_parse_mount_err;
2307 }
2308 }
2309 /* if iocharset not set then load_nls_default
2310 * is used by caller
2311 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002312 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002313 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002314 case Opt_netbiosname:
2315 string = match_strdup(args);
2316 if (string == NULL)
2317 goto out_nomem;
2318
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002319 memset(vol->source_rfc1001_name, 0x20,
2320 RFC1001_NAME_LEN);
2321 /*
2322 * FIXME: are there cases in which a comma can
2323 * be valid in workstation netbios name (and
2324 * need special handling)?
2325 */
2326 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2327 /* don't ucase netbiosname for user */
2328 if (string[i] == 0)
2329 break;
2330 vol->source_rfc1001_name[i] = string[i];
2331 }
2332 /* The string has 16th byte zero still from
2333 * set at top of the function
2334 */
2335 if (i == RFC1001_NAME_LEN && string[i] != 0)
Joe Perchesa0a30362020-04-14 22:42:53 -07002336 pr_warn("netbiosname longer than 15 truncated\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002337 break;
2338 case Opt_servern:
2339 /* servernetbiosname specified override *SMBSERVER */
2340 string = match_strdup(args);
2341 if (string == NULL)
2342 goto out_nomem;
2343
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002344 /* last byte, type, is 0x20 for servr type */
2345 memset(vol->target_rfc1001_name, 0x20,
2346 RFC1001_NAME_LEN_WITH_NULL);
2347
2348 /* BB are there cases in which a comma can be
2349 valid in this workstation netbios name
2350 (and need special handling)? */
2351
2352 /* user or mount helper must uppercase the
2353 netbios name */
2354 for (i = 0; i < 15; i++) {
2355 if (string[i] == 0)
2356 break;
2357 vol->target_rfc1001_name[i] = string[i];
2358 }
2359 /* The string has 16th byte zero still from
2360 set at top of the function */
2361 if (i == RFC1001_NAME_LEN && string[i] != 0)
Joe Perchesa0a30362020-04-14 22:42:53 -07002362 pr_warn("server netbiosname longer than 15 truncated\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002363 break;
2364 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002365 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002366 string = match_strdup(args);
2367 if (string == NULL)
2368 goto out_nomem;
2369
Steve French7e682f72017-08-31 21:34:24 -05002370 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002371 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002372 if (strlen(string) > 1) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002373 pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
2374 string);
Steve French7e682f72017-08-31 21:34:24 -05002375 goto cifs_parse_mount_err;
2376 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002377 /* This is the default */
2378 break;
2379 }
2380 /* For all other value, error */
Joe Perchesa0a30362020-04-14 22:42:53 -07002381 pr_warn("Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002382 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002383 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002384 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002385 string = match_strdup(args);
2386 if (string == NULL)
2387 goto out_nomem;
2388
Steve Frenchc7c137b2018-06-06 17:59:29 -05002389 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002390 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002391 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002392 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002393 case Opt_sec:
2394 string = match_strdup(args);
2395 if (string == NULL)
2396 goto out_nomem;
2397
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002398 if (cifs_parse_security_flavors(string, vol) != 0)
2399 goto cifs_parse_mount_err;
2400 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002401 case Opt_cache:
2402 string = match_strdup(args);
2403 if (string == NULL)
2404 goto out_nomem;
2405
2406 if (cifs_parse_cache_flavor(string, vol) != 0)
2407 goto cifs_parse_mount_err;
2408 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002409 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002410 /*
2411 * An option we don't recognize. Save it off for later
2412 * if we haven't already found one
2413 */
2414 if (!invalid)
2415 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002416 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002418 /* Free up any allocated string */
2419 kfree(string);
2420 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002422
Jeff Laytond8162552012-03-23 14:40:56 -04002423 if (!sloppy && invalid) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002424 pr_err("Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002425 goto cifs_parse_mount_err;
2426 }
2427
Long Li8339dd32017-11-07 01:54:55 -07002428 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2429 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2430 goto cifs_parse_mount_err;
2431 }
2432
Jeff Layton8a8798a2012-01-17 16:09:15 -05002433#ifndef CONFIG_KEYS
2434 /* Muliuser mounts require CONFIG_KEYS support */
2435 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002436 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002437 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002438 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002439#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002440 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002441 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002442 goto cifs_parse_mount_err;
2443 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002444
Jeff Layton62a1a432012-12-10 06:10:45 -05002445 /* make sure UNC has a share name */
2446 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002447 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002448 goto cifs_parse_mount_err;
2449 }
2450
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002451 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002452 int len;
2453 const char *slash;
2454
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002455 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002456 /* Use the address part of the UNC. */
2457 slash = strchr(&vol->UNC[2], '\\');
2458 len = slash - &vol->UNC[2];
2459 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Joe Perchesa0a30362020-04-14 22:42:53 -07002460 pr_err("Unable to determine destination address\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002461 goto cifs_parse_mount_err;
2462 }
2463 }
2464
2465 /* set the port that we got earlier */
2466 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002468 if (uid_specified)
2469 vol->override_uid = override_uid;
2470 else if (override_uid == 1)
Joe Perchesa0a30362020-04-14 22:42:53 -07002471 pr_notice("ignoring forceuid mount option specified with no uid= option\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002472
2473 if (gid_specified)
2474 vol->override_gid = override_gid;
2475 else if (override_gid == 1)
Joe Perchesa0a30362020-04-14 22:42:53 -07002476 pr_notice("ignoring forcegid mount option specified with no gid= option\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002477
Steve French7e682f72017-08-31 21:34:24 -05002478 if (got_version == false)
Joe Perchesa0a30362020-04-14 22:42:53 -07002479 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 -05002480
Sean Finneyb9468452011-04-11 13:19:32 +00002481 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002483
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002484out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002485 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002486cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002487 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002488 kfree(mountdata_copy);
2489 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490}
2491
Ben Greear3eb9a882010-09-01 17:06:02 -07002492/** Returns true if srcaddr isn't specified and rhs isn't
2493 * specified, or if srcaddr is specified and
2494 * matches the IP address of the rhs argument.
2495 */
Paulo Alcantarae4af35f2020-05-19 15:38:28 -03002496bool
2497cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
Ben Greear3eb9a882010-09-01 17:06:02 -07002498{
2499 switch (srcaddr->sa_family) {
2500 case AF_UNSPEC:
2501 return (rhs->sa_family == AF_UNSPEC);
2502 case AF_INET: {
2503 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2504 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2505 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2506 }
2507 case AF_INET6: {
2508 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002509 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002510 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2511 }
2512 default:
2513 WARN_ON(1);
2514 return false; /* don't expect to be here */
2515 }
2516}
2517
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002518/*
2519 * If no port is specified in addr structure, we try to match with 445 port
2520 * and if it fails - with 139 ports. It should be called only if address
2521 * families of server and addr are equal.
2522 */
2523static bool
2524match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2525{
Steve French6da97912011-03-13 18:55:55 +00002526 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002527
Long Li3b249112019-05-15 14:09:04 -07002528 /* SMBDirect manages its own ports, don't match it here */
2529 if (server->rdma)
2530 return true;
2531
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002532 switch (addr->sa_family) {
2533 case AF_INET:
2534 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2535 port = ((struct sockaddr_in *) addr)->sin_port;
2536 break;
2537 case AF_INET6:
2538 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2539 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2540 break;
2541 default:
2542 WARN_ON(1);
2543 return false;
2544 }
2545
2546 if (!port) {
2547 port = htons(CIFS_PORT);
2548 if (port == *sport)
2549 return true;
2550
2551 port = htons(RFC1001_PORT);
2552 }
2553
2554 return port == *sport;
2555}
Ben Greear3eb9a882010-09-01 17:06:02 -07002556
2557static bool
2558match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2559 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560{
Jeff Layton45151482010-07-06 20:43:02 -04002561 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002562 case AF_INET: {
2563 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2564 struct sockaddr_in *srv_addr4 =
2565 (struct sockaddr_in *)&server->dstaddr;
2566
2567 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002568 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002569 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002570 }
2571 case AF_INET6: {
2572 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2573 struct sockaddr_in6 *srv_addr6 =
2574 (struct sockaddr_in6 *)&server->dstaddr;
2575
Jeff Layton45151482010-07-06 20:43:02 -04002576 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002577 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002578 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002579 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002580 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002581 break;
2582 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002583 default:
2584 WARN_ON(1);
2585 return false; /* don't expect to be here */
2586 }
Jeff Layton45151482010-07-06 20:43:02 -04002587
Paulo Alcantarae4af35f2020-05-19 15:38:28 -03002588 if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr))
Ben Greear3eb9a882010-09-01 17:06:02 -07002589 return false;
2590
Jeff Layton45151482010-07-06 20:43:02 -04002591 return true;
2592}
2593
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002594static bool
2595match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2596{
Jeff Layton3f618222013-06-12 19:52:14 -05002597 /*
2598 * The select_sectype function should either return the vol->sectype
2599 * that was specified, or "Unspecified" if that sectype was not
2600 * compatible with the given NEGOTIATE request.
2601 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302602 if (server->ops->select_sectype(server, vol->sectype)
2603 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002604 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002605
Jeff Layton3f618222013-06-12 19:52:14 -05002606 /*
2607 * Now check if signing mode is acceptable. No need to check
2608 * global_secflags at this point since if MUST_SIGN is set then
2609 * the server->sign had better be too.
2610 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002611 if (vol->sign && !server->sign)
2612 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002613
2614 return true;
2615}
2616
Jeff Layton9fa114f2012-11-26 11:09:57 -05002617static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002618{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002619 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2620
Jeff Laytona0b3df52013-05-24 07:40:59 -04002621 if (vol->nosharesock)
2622 return 0;
2623
Steve French43cdae82019-06-13 14:26:49 -05002624 /* If multidialect negotiation see if existing sessions match one */
2625 if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2626 if (server->vals->protocol_id < SMB30_PROT_ID)
2627 return 0;
2628 } else if (strcmp(vol->vals->version_string,
2629 SMBDEFAULT_VERSION_STRING) == 0) {
2630 if (server->vals->protocol_id < SMB21_PROT_ID)
2631 return 0;
2632 } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
Jeff Layton23db65f2012-05-15 12:20:51 -04002633 return 0;
2634
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002635 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2636 return 0;
2637
2638 if (!match_address(server, addr,
2639 (struct sockaddr *)&vol->srcaddr))
2640 return 0;
2641
2642 if (!match_port(server, addr))
2643 return 0;
2644
2645 if (!match_security(server, vol))
2646 return 0;
2647
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002648 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002649 return 0;
2650
Long Li8339dd32017-11-07 01:54:55 -07002651 if (server->rdma != vol->rdma)
2652 return 0;
2653
Steve French4f5c10f2019-09-03 21:18:49 -05002654 if (server->ignore_signature != vol->ignore_signature)
2655 return 0;
2656
Steve French563317e2019-09-08 23:22:02 -05002657 if (server->min_offload != vol->min_offload)
2658 return 0;
2659
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002660 return 1;
2661}
2662
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002663struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002664cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002665{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002666 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302668 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002669 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Paulo Alcantara (SUSE)3345bb42019-12-04 11:25:06 -03002670 /*
2671 * Skip ses channels since they're only handled in lower layers
2672 * (e.g. cifs_send_recv).
2673 */
2674 if (server->is_channel || !match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002675 continue;
2676
Jeff Laytone7ddee92008-11-14 13:44:38 -05002677 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302678 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002679 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002680 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302682 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 return NULL;
2684}
2685
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002686void
2687cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002689 struct task_struct *task;
2690
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302691 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002692 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302693 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002694 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002696
Rob Landleyf1d0c992011-01-22 15:44:05 -06002697 put_net(cifs_net_ns(server));
2698
Jeff Laytone7ddee92008-11-14 13:44:38 -05002699 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302700 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002701
Jeff Laytonc74093b2011-01-11 07:24:23 -05002702 cancel_delayed_work_sync(&server->echo);
2703
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002704 if (from_reconnect)
2705 /*
2706 * Avoid deadlock here: reconnect work calls
2707 * cifs_put_tcp_session() at its end. Need to be sure
2708 * that reconnect work does nothing with server pointer after
2709 * that step.
2710 */
2711 cancel_delayed_work(&server->reconnect);
2712 else
2713 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002714
Jeff Laytone7ddee92008-11-14 13:44:38 -05002715 spin_lock(&GlobalMid_Lock);
2716 server->tcpStatus = CifsExiting;
2717 spin_unlock(&GlobalMid_Lock);
2718
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002719 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302720 cifs_fscache_release_client_cookie(server);
2721
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002722 kfree(server->session_key.response);
2723 server->session_key.response = NULL;
2724 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002725
2726 task = xchg(&server->tsk, NULL);
2727 if (task)
Eric W. Biederman72abe3b2019-05-15 12:33:50 -05002728 send_sig(SIGKILL, task, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729}
2730
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02002731struct TCP_Server_Info *
Jeff Layton63c038c2008-12-01 18:41:46 -05002732cifs_get_tcp_session(struct smb_vol *volume_info)
2733{
2734 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002735 int rc;
2736
Joe Perchesf96637b2013-05-04 22:12:25 -05002737 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002738
2739 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002740 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002741 if (tcp_ses)
2742 return tcp_ses;
2743
2744 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2745 if (!tcp_ses) {
2746 rc = -ENOMEM;
2747 goto out_err;
2748 }
2749
Jeff Layton23db65f2012-05-15 12:20:51 -04002750 tcp_ses->ops = volume_info->ops;
2751 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002752 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002753 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2754 if (IS_ERR(tcp_ses->hostname)) {
2755 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002756 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002757 }
2758
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03002759 tcp_ses->noblockcnt = volume_info->rootfs;
2760 tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
Jeff Layton63c038c2008-12-01 18:41:46 -05002761 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002762 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002763 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002764 tcp_ses->in_flight = 0;
Steve French1b63f182019-09-09 22:57:11 -05002765 tcp_ses->max_in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002766 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002767 init_waitqueue_head(&tcp_ses->response_q);
2768 init_waitqueue_head(&tcp_ses->request_q);
2769 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2770 mutex_init(&tcp_ses->srv_mutex);
2771 memcpy(tcp_ses->workstation_RFC1001_name,
2772 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2773 memcpy(tcp_ses->server_RFC1001_name,
2774 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002775 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002776 tcp_ses->sequence_number = 0;
Pavel Shilovsky5b964852019-01-18 11:30:26 -08002777 tcp_ses->reconnect_instance = 1;
Steve Frenchfda35942011-01-20 18:06:34 +00002778 tcp_ses->lstrp = jiffies;
Steve French9fe5ff12019-06-24 20:39:04 -05002779 tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
Jeff Layton58fa0152012-05-01 17:41:16 -04002780 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002781 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2782 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002783 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002784 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2785 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002786 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2787 sizeof(tcp_ses->srcaddr));
2788 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2789 sizeof(tcp_ses->dstaddr));
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002790 if (volume_info->use_client_guid)
2791 memcpy(tcp_ses->client_guid, volume_info->client_guid,
2792 SMB2_CLIENT_GUID_SIZE);
2793 else
2794 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002795 /*
2796 * at this point we are the only ones with the pointer
2797 * to the struct since the kernel thread not created yet
2798 * no need to spinlock this init of tcpStatus or srv_count
2799 */
2800 tcp_ses->tcpStatus = CifsNew;
2801 ++tcp_ses->srv_count;
2802
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002803 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2804 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2805 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2806 else
2807 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002808 if (tcp_ses->rdma) {
2809#ifndef CONFIG_CIFS_SMB_DIRECT
2810 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2811 rc = -ENOENT;
2812 goto out_err_crypto_release;
2813#endif
2814 tcp_ses->smbd_conn = smbd_get_connection(
2815 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2816 if (tcp_ses->smbd_conn) {
2817 cifs_dbg(VFS, "RDMA transport established\n");
2818 rc = 0;
2819 goto smbd_connected;
2820 } else {
2821 rc = -ENOENT;
2822 goto out_err_crypto_release;
2823 }
2824 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002825 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002826 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002827 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002828 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002829 }
Long Li2f894642017-11-22 17:38:34 -07002830smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002831 /*
2832 * since we're in a cifs function already, we know that
2833 * this will succeed. No need for try_module_get().
2834 */
2835 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002836 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002837 tcp_ses, "cifsd");
2838 if (IS_ERR(tcp_ses->tsk)) {
2839 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002840 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002841 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002842 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002843 }
Steve French563317e2019-09-08 23:22:02 -05002844 tcp_ses->min_offload = volume_info->min_offload;
Steve Frenchfd88ce92011-04-12 01:01:14 +00002845 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002846
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002847 tcp_ses->nr_targets = 1;
Steve French4f5c10f2019-09-03 21:18:49 -05002848 tcp_ses->ignore_signature = volume_info->ignore_signature;
Jeff Layton63c038c2008-12-01 18:41:46 -05002849 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302850 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002851 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302852 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002853
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302854 cifs_fscache_get_client_cookie(tcp_ses);
2855
Jeff Laytonc74093b2011-01-11 07:24:23 -05002856 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002857 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002858
Jeff Layton63c038c2008-12-01 18:41:46 -05002859 return tcp_ses;
2860
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002861out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002862 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002863
Rob Landleyf1d0c992011-01-22 15:44:05 -06002864 put_net(cifs_net_ns(tcp_ses));
2865
Jeff Layton63c038c2008-12-01 18:41:46 -05002866out_err:
2867 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002868 if (!IS_ERR(tcp_ses->hostname))
2869 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002870 if (tcp_ses->ssocket)
2871 sock_release(tcp_ses->ssocket);
2872 kfree(tcp_ses);
2873 }
2874 return ERR_PTR(rc);
2875}
2876
Steve French96daf2b2011-05-27 04:34:02 +00002877static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002878{
Jeff Layton3f618222013-06-12 19:52:14 -05002879 if (vol->sectype != Unspecified &&
2880 vol->sectype != ses->sectype)
2881 return 0;
2882
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002883 /*
2884 * If an existing session is limited to less channels than
2885 * requested, it should not be reused
2886 */
2887 if (ses->chan_max < vol->max_channels)
2888 return 0;
2889
Jeff Layton3f618222013-06-12 19:52:14 -05002890 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002891 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002892 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002893 return 0;
2894 break;
2895 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002896 /* NULL username means anonymous session */
2897 if (ses->user_name == NULL) {
2898 if (!vol->nullauth)
2899 return 0;
2900 break;
2901 }
2902
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002903 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002904 if (strncmp(ses->user_name,
2905 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002906 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002907 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002908 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002909 ses->password != NULL &&
2910 strncmp(ses->password,
2911 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002912 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002913 return 0;
2914 }
2915 return 1;
2916}
2917
Aurelien Aptelb327a712018-01-24 13:46:10 +01002918/**
2919 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2920 *
2921 * A new IPC connection is made and stored in the session
2922 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2923 */
2924static int
2925cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2926{
2927 int rc = 0, xid;
2928 struct cifs_tcon *tcon;
2929 struct nls_table *nls_codepage;
2930 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2931 bool seal = false;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002932 struct TCP_Server_Info *server = ses->server;
Aurelien Aptelb327a712018-01-24 13:46:10 +01002933
2934 /*
2935 * If the mount request that resulted in the creation of the
2936 * session requires encryption, force IPC to be encrypted too.
2937 */
2938 if (volume_info->seal) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002939 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
Aurelien Aptelb327a712018-01-24 13:46:10 +01002940 seal = true;
2941 else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002942 cifs_server_dbg(VFS,
Aurelien Aptelb327a712018-01-24 13:46:10 +01002943 "IPC: server doesn't support encryption\n");
2944 return -EOPNOTSUPP;
2945 }
2946 }
2947
2948 tcon = tconInfoAlloc();
2949 if (tcon == NULL)
2950 return -ENOMEM;
2951
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002952 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002953
2954 /* cannot fail */
2955 nls_codepage = load_nls_default();
2956
2957 xid = get_xid();
2958 tcon->ses = ses;
2959 tcon->ipc = true;
2960 tcon->seal = seal;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002961 rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002962 free_xid(xid);
2963
2964 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002965 cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002966 tconInfoFree(tcon);
2967 goto out;
2968 }
2969
2970 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2971
2972 ses->tcon_ipc = tcon;
2973out:
2974 unload_nls(nls_codepage);
2975 return rc;
2976}
2977
2978/**
2979 * cifs_free_ipc - helper to release the session IPC tcon
2980 *
2981 * Needs to be called everytime a session is destroyed
2982 */
2983static int
2984cifs_free_ipc(struct cifs_ses *ses)
2985{
2986 int rc = 0, xid;
2987 struct cifs_tcon *tcon = ses->tcon_ipc;
2988
2989 if (tcon == NULL)
2990 return 0;
2991
2992 if (ses->server->ops->tree_disconnect) {
2993 xid = get_xid();
2994 rc = ses->server->ops->tree_disconnect(xid, tcon);
2995 free_xid(xid);
2996 }
2997
2998 if (rc)
2999 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
3000
3001 tconInfoFree(tcon);
3002 ses->tcon_ipc = NULL;
3003 return rc;
3004}
3005
Steve French96daf2b2011-05-27 04:34:02 +00003006static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04003007cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008{
Steve French96daf2b2011-05-27 04:34:02 +00003009 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303011 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04003012 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003013 if (ses->status == CifsExiting)
3014 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003015 if (!match_session(ses, vol))
3016 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05003017 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303018 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003019 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303021 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 return NULL;
3023}
3024
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003025void cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05003026{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003027 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05003028 struct TCP_Server_Info *server = ses->server;
3029
Joe Perchesf96637b2013-05-04 22:12:25 -05003030 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003031
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303032 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003033 if (ses->status == CifsExiting) {
3034 spin_unlock(&cifs_tcp_ses_lock);
3035 return;
3036 }
Jeff Layton14fbf502008-11-14 13:53:46 -05003037 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303038 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003039 return;
3040 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003041 if (ses->status == CifsGood)
3042 ses->status = CifsExiting;
3043 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003044
Aurelien Aptelb327a712018-01-24 13:46:10 +01003045 cifs_free_ipc(ses);
3046
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003047 if (ses->status == CifsExiting && server->ops->logoff) {
3048 xid = get_xid();
3049 rc = server->ops->logoff(xid, ses);
3050 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003051 cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003052 __func__, rc);
3053 _free_xid(xid);
3054 }
3055
3056 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003057 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303058 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003059
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003060 /* close any extra channels */
3061 if (ses->chan_count > 1) {
3062 int i;
3063
3064 for (i = 1; i < ses->chan_count; i++)
3065 cifs_put_tcp_session(ses->chans[i].server, 0);
3066 }
3067
Jeff Layton14fbf502008-11-14 13:53:46 -05003068 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003069 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05003070}
3071
Jeff Layton8a8798a2012-01-17 16:09:15 -05003072#ifdef CONFIG_KEYS
3073
Chen Gang057d6332013-07-19 09:01:36 +08003074/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
3075#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05003076
3077/* Populate username and pw fields from keyring if possible */
3078static int
3079cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
3080{
3081 int rc = 0;
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003082 int is_domain = 0;
David Howells146aa8b2015-10-21 14:04:48 +01003083 const char *delim, *payload;
3084 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003085 ssize_t len;
3086 struct key *key;
3087 struct TCP_Server_Info *server = ses->server;
3088 struct sockaddr_in *sa;
3089 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01003090 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003091
3092 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
3093 if (!desc)
3094 return -ENOMEM;
3095
3096 /* try to find an address key first */
3097 switch (server->dstaddr.ss_family) {
3098 case AF_INET:
3099 sa = (struct sockaddr_in *)&server->dstaddr;
3100 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
3101 break;
3102 case AF_INET6:
3103 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
3104 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
3105 break;
3106 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05003107 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
3108 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003109 rc = -EINVAL;
3110 goto out_err;
3111 }
3112
Joe Perchesf96637b2013-05-04 22:12:25 -05003113 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003114 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003115 if (IS_ERR(key)) {
3116 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003117 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003118 rc = PTR_ERR(key);
3119 goto out_err;
3120 }
3121
3122 /* didn't work, try to find a domain key */
3123 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05003124 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003125 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003126 if (IS_ERR(key)) {
3127 rc = PTR_ERR(key);
3128 goto out_err;
3129 }
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003130 is_domain = 1;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003131 }
3132
3133 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00003134 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003135 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05003136 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003137 goto out_key_put;
3138 }
3139
3140 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01003141 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003142 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05003143 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003144 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003145 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
3146 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003147 rc = -EINVAL;
3148 goto out_key_put;
3149 }
3150
3151 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003152 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003153 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
3154 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003155 rc = -EINVAL;
3156 goto out_key_put;
3157 }
3158
3159 vol->username = kstrndup(payload, len, GFP_KERNEL);
3160 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003161 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
3162 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003163 rc = -ENOMEM;
3164 goto out_key_put;
3165 }
Joe Perchesf96637b2013-05-04 22:12:25 -05003166 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003167
3168 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003169 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003170 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003171 rc = -EINVAL;
3172 kfree(vol->username);
3173 vol->username = NULL;
3174 goto out_key_put;
3175 }
3176
3177 ++delim;
3178 vol->password = kstrndup(delim, len, GFP_KERNEL);
3179 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003180 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
3181 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003182 rc = -ENOMEM;
3183 kfree(vol->username);
3184 vol->username = NULL;
3185 goto out_key_put;
3186 }
3187
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003188 /*
3189 * If we have a domain key then we must set the domainName in the
3190 * for the request.
3191 */
3192 if (is_domain && ses->domainName) {
3193 vol->domainname = kstrndup(ses->domainName,
3194 strlen(ses->domainName),
3195 GFP_KERNEL);
3196 if (!vol->domainname) {
Joe Perchesa0a30362020-04-14 22:42:53 -07003197 cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
3198 len);
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003199 rc = -ENOMEM;
3200 kfree(vol->username);
3201 vol->username = NULL;
Waiman Long453431a2020-08-06 23:18:13 -07003202 kfree_sensitive(vol->password);
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003203 vol->password = NULL;
3204 goto out_key_put;
3205 }
3206 }
3207
Jeff Layton8a8798a2012-01-17 16:09:15 -05003208out_key_put:
3209 up_read(&key->sem);
3210 key_put(key);
3211out_err:
3212 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05003213 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003214 return rc;
3215}
3216#else /* ! CONFIG_KEYS */
3217static inline int
3218cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
3219 struct cifs_ses *ses __attribute__((unused)))
3220{
3221 return -ENOSYS;
3222}
3223#endif /* CONFIG_KEYS */
3224
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003225/**
3226 * cifs_get_smb_ses - get a session matching @volume_info data from @server
3227 *
3228 * This function assumes it is being called from cifs_mount() where we
3229 * already got a server reference (server refcount +1). See
3230 * cifs_get_tcon() for refcount explanations.
3231 */
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003232struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04003233cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3234{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003235 int rc = -ENOMEM;
3236 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003237 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003238 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3239 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04003240
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003241 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04003242
Jeff Layton4ff67b72010-07-06 20:43:02 -04003243 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04003244 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003245 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3246 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04003247
Jeff Layton36988c72010-04-24 07:57:43 -04003248 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003249 rc = cifs_negotiate_protocol(xid, ses);
3250 if (rc) {
3251 mutex_unlock(&ses->session_mutex);
3252 /* problem -- put our ses reference */
3253 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003254 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003255 return ERR_PTR(rc);
3256 }
Jeff Layton36988c72010-04-24 07:57:43 -04003257 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003258 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003259 rc = cifs_setup_session(xid, ses,
3260 volume_info->local_nls);
3261 if (rc) {
3262 mutex_unlock(&ses->session_mutex);
3263 /* problem -- put our reference */
3264 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003265 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003266 return ERR_PTR(rc);
3267 }
3268 }
3269 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003270
3271 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003272 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003273 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003274 return ses;
3275 }
3276
Joe Perchesf96637b2013-05-04 22:12:25 -05003277 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003278 ses = sesInfoAlloc();
3279 if (ses == NULL)
3280 goto get_ses_fail;
3281
3282 /* new SMB session uses our server ref */
3283 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003284 if (server->dstaddr.ss_family == AF_INET6)
3285 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003286 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003287 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003288
Steve French8727c8a2011-02-25 01:11:56 -06003289 if (volume_info->username) {
3290 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3291 if (!ses->user_name)
3292 goto get_ses_fail;
3293 }
Jeff Layton36988c72010-04-24 07:57:43 -04003294
3295 /* volume_info->password freed at unmount */
3296 if (volume_info->password) {
3297 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3298 if (!ses->password)
3299 goto get_ses_fail;
3300 }
3301 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003302 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3303 if (!ses->domainName)
3304 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003305 }
Germano Percossi39566442016-12-15 12:31:18 +05303306 if (volume_info->domainauto)
3307 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003308 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003309 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003310
Jeff Layton28e11bd2013-05-26 07:01:00 -04003311 ses->sectype = volume_info->sectype;
3312 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003313 mutex_lock(&ses->session_mutex);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003314
3315 /* add server as first channel */
3316 ses->chans[0].server = server;
3317 ses->chan_count = 1;
3318 ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1;
3319
Jeff Layton198b5682010-04-24 07:57:48 -04003320 rc = cifs_negotiate_protocol(xid, ses);
3321 if (!rc)
3322 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003323
3324 /* each channel uses a different signing key */
3325 memcpy(ses->chans[0].signkey, ses->smb3signingkey,
3326 sizeof(ses->smb3signingkey));
3327
Jeff Layton36988c72010-04-24 07:57:43 -04003328 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003329 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003330 goto get_ses_fail;
3331
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003332 /* success, put it on the list and add it as first channel */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303333 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003334 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303335 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003336
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003337 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003338
3339 cifs_setup_ipc(ses, volume_info);
3340
Jeff Layton36988c72010-04-24 07:57:43 -04003341 return ses;
3342
3343get_ses_fail:
3344 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003345 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003346 return ERR_PTR(rc);
3347}
3348
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003349static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003350{
3351 if (tcon->tidStatus == CifsExiting)
3352 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003353 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003354 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003355 if (tcon->seal != volume_info->seal)
3356 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003357 if (tcon->snapshot_time != volume_info->snapshot_time)
3358 return 0;
Steve Frenchca567eb2019-03-29 16:31:07 -05003359 if (tcon->handle_timeout != volume_info->handle_timeout)
3360 return 0;
Steve French3e7a02d2019-09-11 21:46:20 -05003361 if (tcon->no_lease != volume_info->no_lease)
3362 return 0;
Steve French82e93672020-05-19 03:06:57 -05003363 if (tcon->nodelete != volume_info->nodelete)
3364 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003365 return 1;
3366}
3367
Steve French96daf2b2011-05-27 04:34:02 +00003368static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003369cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370{
3371 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003372 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303374 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003375 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003376 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Paulo Alcantara65303de2020-04-20 19:42:57 -03003377#ifdef CONFIG_CIFS_DFS_UPCALL
3378 if (tcon->dfs_path)
3379 continue;
3380#endif
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003381 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003382 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003383 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303384 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 return tcon;
3386 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303387 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388 return NULL;
3389}
3390
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003391void
Steve French96daf2b2011-05-27 04:34:02 +00003392cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003393{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003394 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003395 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003396
Aurelien Aptelb327a712018-01-24 13:46:10 +01003397 /*
3398 * IPC tcon share the lifetime of their session and are
3399 * destroyed in the session put function
3400 */
3401 if (tcon == NULL || tcon->ipc)
3402 return;
3403
3404 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003405 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303406 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003407 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303408 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003409 return;
3410 }
3411
3412 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303413 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003414
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003415 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003416 if (ses->server->ops->tree_disconnect)
3417 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003418 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003419
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303420 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003421 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003422 cifs_put_smb_ses(ses);
3423}
3424
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003425/**
3426 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3427 *
3428 * - tcon refcount is the number of mount points using the tcon.
3429 * - ses refcount is the number of tcon using the session.
3430 *
3431 * 1. This function assumes it is being called from cifs_mount() where
3432 * we already got a session reference (ses refcount +1).
3433 *
3434 * 2. Since we're in the context of adding a mount point, the end
3435 * result should be either:
3436 *
3437 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3438 * its session refcount incremented (1 new tcon). This +1 was
3439 * already done in (1).
3440 *
3441 * b) an existing tcon with refcount+1 (add a mount point to it) and
3442 * identical ses refcount (no new tcon). Because of (1) we need to
3443 * decrement the ses refcount.
3444 */
Steve French96daf2b2011-05-27 04:34:02 +00003445static struct cifs_tcon *
3446cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003447{
3448 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003449 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003450
Steve French8b217fe2016-11-11 22:36:20 -06003451 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003452 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003453 /*
3454 * tcon has refcount already incremented but we need to
3455 * decrement extra ses reference gotten by caller (case b)
3456 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003457 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003458 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003459 return tcon;
3460 }
3461
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003462 if (!ses->server->ops->tree_connect) {
3463 rc = -ENOSYS;
3464 goto out_fail;
3465 }
3466
Jeff Laytond00c28d2010-04-24 07:57:44 -04003467 tcon = tconInfoAlloc();
3468 if (tcon == NULL) {
3469 rc = -ENOMEM;
3470 goto out_fail;
3471 }
3472
Steve French8b217fe2016-11-11 22:36:20 -06003473 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003474 if (ses->server->vals->protocol_id == 0) {
3475 cifs_dbg(VFS,
3476 "Use SMB2 or later for snapshot mount option\n");
3477 rc = -EOPNOTSUPP;
3478 goto out_fail;
3479 } else
3480 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003481 }
3482
Steve Frenchca567eb2019-03-29 16:31:07 -05003483 if (volume_info->handle_timeout) {
3484 if (ses->server->vals->protocol_id == 0) {
3485 cifs_dbg(VFS,
3486 "Use SMB2.1 or later for handle timeout option\n");
3487 rc = -EOPNOTSUPP;
3488 goto out_fail;
3489 } else
3490 tcon->handle_timeout = volume_info->handle_timeout;
3491 }
3492
Jeff Laytond00c28d2010-04-24 07:57:44 -04003493 tcon->ses = ses;
3494 if (volume_info->password) {
3495 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3496 if (!tcon->password) {
3497 rc = -ENOMEM;
3498 goto out_fail;
3499 }
3500 }
3501
Steve French23657ad2018-04-22 15:14:58 -05003502 if (volume_info->seal) {
3503 if (ses->server->vals->protocol_id == 0) {
3504 cifs_dbg(VFS,
3505 "SMB3 or later required for encryption\n");
3506 rc = -EOPNOTSUPP;
3507 goto out_fail;
3508 } else if (tcon->ses->server->capabilities &
3509 SMB2_GLOBAL_CAP_ENCRYPTION)
3510 tcon->seal = true;
3511 else {
3512 cifs_dbg(VFS, "Encryption is not supported on share\n");
3513 rc = -EOPNOTSUPP;
3514 goto out_fail;
3515 }
3516 }
3517
Steve French8505c8b2018-06-18 14:01:59 -05003518 if (volume_info->linux_ext) {
3519 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003520 tcon->posix_extensions = true;
Joe Perchesa0a30362020-04-14 22:42:53 -07003521 pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003522 } else {
Joe Perchesa0a30362020-04-14 22:42:53 -07003523 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
Steve French8505c8b2018-06-18 14:01:59 -05003524 rc = -EOPNOTSUPP;
3525 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003526 }
Steve Frenchb3266142018-05-20 23:41:10 -05003527 }
Steve Frenchb3266142018-05-20 23:41:10 -05003528
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003529 /*
3530 * BB Do we need to wrap session_mutex around this TCon call and Unix
3531 * SetFS as we do on SessSetup and reconnect?
3532 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003533 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003534 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3535 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003536 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003537 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003538 if (rc)
3539 goto out_fail;
3540
Steve Frenchb618f002015-11-03 09:15:03 -06003541 tcon->use_persistent = false;
3542 /* check if SMB2 or later, CIFS does not support persistent handles */
3543 if (volume_info->persistent) {
3544 if (ses->server->vals->protocol_id == 0) {
3545 cifs_dbg(VFS,
3546 "SMB3 or later required for persistent handles\n");
3547 rc = -EOPNOTSUPP;
3548 goto out_fail;
3549 } else if (ses->server->capabilities &
3550 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3551 tcon->use_persistent = true;
3552 else /* persistent handles requested but not supported */ {
3553 cifs_dbg(VFS,
3554 "Persistent handles not supported on share\n");
3555 rc = -EOPNOTSUPP;
3556 goto out_fail;
3557 }
3558 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3559 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3560 && (volume_info->nopersistent == false)) {
3561 cifs_dbg(FYI, "enabling persistent handles\n");
3562 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003563 } else if (volume_info->resilient) {
3564 if (ses->server->vals->protocol_id == 0) {
3565 cifs_dbg(VFS,
3566 "SMB2.1 or later required for resilient handles\n");
3567 rc = -EOPNOTSUPP;
3568 goto out_fail;
3569 }
3570 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003571 }
3572
Steve Frenchcae53f72019-09-03 17:49:46 -05003573 /* If the user really knows what they are doing they can override */
3574 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3575 if (volume_info->cache_ro)
3576 cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3577 else if (volume_info->cache_rw)
3578 cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3579 }
3580
Kenneth D'souza8fd6e1d2020-05-18 13:01:34 +05303581 if (volume_info->no_lease) {
3582 if (ses->server->vals->protocol_id == 0) {
3583 cifs_dbg(VFS,
3584 "SMB2 or later required for nolease option\n");
3585 rc = -EOPNOTSUPP;
3586 goto out_fail;
3587 } else
3588 tcon->no_lease = volume_info->no_lease;
3589 }
3590
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003591 /*
3592 * We can have only one retry value for a connection to a share so for
3593 * resources mounted more than once to the same server share the last
3594 * value passed in for the retry flag is used.
3595 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003596 tcon->retry = volume_info->retry;
3597 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003598 tcon->nohandlecache = volume_info->nohandlecache;
Steve French82e93672020-05-19 03:06:57 -05003599 tcon->nodelete = volume_info->nodelete;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003600 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003601 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003602
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303603 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003604 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303605 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003606
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303607 cifs_fscache_get_super_cookie(tcon);
3608
Jeff Laytond00c28d2010-04-24 07:57:44 -04003609 return tcon;
3610
3611out_fail:
3612 tconInfoFree(tcon);
3613 return ERR_PTR(rc);
3614}
3615
Jeff Layton9d002df2010-10-06 19:51:11 -04003616void
3617cifs_put_tlink(struct tcon_link *tlink)
3618{
3619 if (!tlink || IS_ERR(tlink))
3620 return;
3621
3622 if (!atomic_dec_and_test(&tlink->tl_count) ||
3623 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3624 tlink->tl_time = jiffies;
3625 return;
3626 }
3627
3628 if (!IS_ERR(tlink_tcon(tlink)))
3629 cifs_put_tcon(tlink_tcon(tlink));
3630 kfree(tlink);
3631 return;
3632}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003633
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003634static int
3635compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3636{
3637 struct cifs_sb_info *old = CIFS_SB(sb);
3638 struct cifs_sb_info *new = mnt_data->cifs_sb;
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003639 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3640 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003641
3642 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3643 return 0;
3644
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003645 if (old->mnt_cifs_serverino_autodisabled)
3646 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3647
3648 if (oldflags != newflags)
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003649 return 0;
3650
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003651 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003652 * We want to share sb only if we don't specify an r/wsize or
3653 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003654 */
3655 if (new->wsize && new->wsize < old->wsize)
3656 return 0;
3657
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003658 if (new->rsize && new->rsize < old->rsize)
3659 return 0;
3660
Eric W. Biederman1f682332013-02-06 01:20:20 -08003661 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003662 return 0;
3663
3664 if (old->mnt_file_mode != new->mnt_file_mode ||
3665 old->mnt_dir_mode != new->mnt_dir_mode)
3666 return 0;
3667
3668 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3669 return 0;
3670
3671 if (old->actimeo != new->actimeo)
3672 return 0;
3673
3674 return 1;
3675}
3676
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003677static int
3678match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3679{
3680 struct cifs_sb_info *old = CIFS_SB(sb);
3681 struct cifs_sb_info *new = mnt_data->cifs_sb;
Ronnie Sahlbergfe129262020-01-22 11:07:56 +10003682 bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3683 old->prepath;
3684 bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3685 new->prepath;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003686
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003687 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003688 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003689 else if (!old_set && !new_set)
3690 return 1;
3691
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003692 return 0;
3693}
3694
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003695int
3696cifs_match_super(struct super_block *sb, void *data)
3697{
3698 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3699 struct smb_vol *volume_info;
3700 struct cifs_sb_info *cifs_sb;
3701 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003702 struct cifs_ses *ses;
3703 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003704 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003705 int rc = 0;
3706
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003707 spin_lock(&cifs_tcp_ses_lock);
3708 cifs_sb = CIFS_SB(sb);
3709 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3710 if (IS_ERR(tlink)) {
3711 spin_unlock(&cifs_tcp_ses_lock);
3712 return rc;
3713 }
3714 tcon = tlink_tcon(tlink);
3715 ses = tcon->ses;
3716 tcp_srv = ses->server;
3717
3718 volume_info = mnt_data->vol;
3719
Jeff Layton9fa114f2012-11-26 11:09:57 -05003720 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003721 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003722 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003723 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003724 rc = 0;
3725 goto out;
3726 }
3727
3728 rc = compare_mount_options(sb, mnt_data);
3729out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003730 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003731 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003732 return rc;
3733}
3734
Jeff Layton09e50d52008-07-23 10:11:19 -04003735#ifdef CONFIG_DEBUG_LOCK_ALLOC
3736static struct lock_class_key cifs_key[2];
3737static struct lock_class_key cifs_slock_key[2];
3738
3739static inline void
3740cifs_reclassify_socket4(struct socket *sock)
3741{
3742 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003743 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003744 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3745 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3746}
3747
3748static inline void
3749cifs_reclassify_socket6(struct socket *sock)
3750{
3751 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003752 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003753 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3754 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3755}
3756#else
3757static inline void
3758cifs_reclassify_socket4(struct socket *sock)
3759{
3760}
3761
3762static inline void
3763cifs_reclassify_socket6(struct socket *sock)
3764{
3765}
3766#endif
3767
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003769static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770{
Steve French50c2f752007-07-13 00:33:32 +00003771 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772
Steve French50c2f752007-07-13 00:33:32 +00003773 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 /* mask a nibble at a time and encode */
3775 target[j] = 'A' + (0x0F & (source[i] >> 4));
3776 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003777 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 }
3779
3780}
3781
Ben Greear3eb9a882010-09-01 17:06:02 -07003782static int
3783bind_socket(struct TCP_Server_Info *server)
3784{
3785 int rc = 0;
3786 if (server->srcaddr.ss_family != AF_UNSPEC) {
3787 /* Bind to the specified local IP address */
3788 struct socket *socket = server->ssocket;
3789 rc = socket->ops->bind(socket,
3790 (struct sockaddr *) &server->srcaddr,
3791 sizeof(server->srcaddr));
3792 if (rc < 0) {
3793 struct sockaddr_in *saddr4;
3794 struct sockaddr_in6 *saddr6;
3795 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3796 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3797 if (saddr6->sin6_family == AF_INET6)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003798 cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003799 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003800 else
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003801 cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003802 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003803 }
3804 }
3805 return rc;
3806}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
3808static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003809ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810{
3811 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003812 /*
3813 * some servers require RFC1001 sessinit before sending
3814 * negprot - BB check reconnection in case where second
3815 * sessinit is sent but no second negprot
3816 */
3817 struct rfc1002_session_packet *ses_init_buf;
3818 struct smb_hdr *smb_buf;
3819 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3820 GFP_KERNEL);
3821 if (ses_init_buf) {
3822 ses_init_buf->trailer.session_req.called_len = 32;
3823
Colin Ian King997152f2016-01-25 16:25:54 +00003824 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003825 rfc1002mangle(ses_init_buf->trailer.
3826 session_req.called_name,
3827 server->server_RFC1001_name,
3828 RFC1001_NAME_LEN_WITH_NULL);
3829 else
3830 rfc1002mangle(ses_init_buf->trailer.
3831 session_req.called_name,
3832 DEFAULT_CIFS_CALLED_NAME,
3833 RFC1001_NAME_LEN_WITH_NULL);
3834
3835 ses_init_buf->trailer.session_req.calling_len = 32;
3836
3837 /*
3838 * calling name ends in null (byte 16) from old smb
3839 * convention.
3840 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003841 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003842 rfc1002mangle(ses_init_buf->trailer.
3843 session_req.calling_name,
3844 server->workstation_RFC1001_name,
3845 RFC1001_NAME_LEN_WITH_NULL);
3846 else
3847 rfc1002mangle(ses_init_buf->trailer.
3848 session_req.calling_name,
3849 "LINUX_CIFS_CLNT",
3850 RFC1001_NAME_LEN_WITH_NULL);
3851
3852 ses_init_buf->trailer.session_req.scope1 = 0;
3853 ses_init_buf->trailer.session_req.scope2 = 0;
3854 smb_buf = (struct smb_hdr *)ses_init_buf;
3855
3856 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003857 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003858 rc = smb_send(server, smb_buf, 0x44);
3859 kfree(ses_init_buf);
3860 /*
3861 * RFC1001 layer in at least one server
3862 * requires very short break before negprot
3863 * presumably because not expecting negprot
3864 * to follow so fast. This is a simple
3865 * solution that works without
3866 * complicating the code and causes no
3867 * significant slowing down on mount
3868 * for everyone else
3869 */
3870 usleep_range(1000, 2000);
3871 }
3872 /*
3873 * else the negprot may still work without this
3874 * even though malloc failed
3875 */
3876
3877 return rc;
3878}
3879
3880static int
3881generic_ip_connect(struct TCP_Server_Info *server)
3882{
3883 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003884 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003885 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003886 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003887 struct sockaddr *saddr;
3888
3889 saddr = (struct sockaddr *) &server->dstaddr;
3890
3891 if (server->dstaddr.ss_family == AF_INET6) {
3892 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3893 slen = sizeof(struct sockaddr_in6);
3894 sfamily = AF_INET6;
3895 } else {
3896 sport = ((struct sockaddr_in *) saddr)->sin_port;
3897 slen = sizeof(struct sockaddr_in);
3898 sfamily = AF_INET;
3899 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003901 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003902 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3903 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 if (rc < 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003905 cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003906 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003909
3910 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003911 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003912 server->ssocket = socket;
3913 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003914 if (sfamily == AF_INET6)
3915 cifs_reclassify_socket6(socket);
3916 else
3917 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 }
3919
Ben Greear3eb9a882010-09-01 17:06:02 -07003920 rc = bind_socket(server);
3921 if (rc < 0)
3922 return rc;
3923
Jeff Laytond5c56052008-12-01 18:42:33 -05003924 /*
3925 * Eventually check for other socket options to change from
3926 * the default. sock_setsockopt not used because it expects
3927 * user space buffer
3928 */
3929 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003930 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003931
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003932 /* make the bufsizes depend on wsize/rsize and max requests */
3933 if (server->noautotune) {
3934 if (socket->sk->sk_sndbuf < (200 * 1024))
3935 socket->sk->sk_sndbuf = 200 * 1024;
3936 if (socket->sk->sk_rcvbuf < (140 * 1024))
3937 socket->sk->sk_rcvbuf = 140 * 1024;
3938 }
3939
Christoph Hellwig12abc5e2020-05-28 07:12:19 +02003940 if (server->tcp_nodelay)
3941 tcp_sock_set_nodelay(socket->sk);
Steve French6a5fa2362010-01-01 01:28:43 +00003942
Joe Perchesf96637b2013-05-04 22:12:25 -05003943 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003944 socket->sk->sk_sndbuf,
3945 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3946
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003947 rc = socket->ops->connect(socket, saddr, slen,
3948 server->noblockcnt ? O_NONBLOCK : 0);
Paulo Alcantara (SUSE)d532cc72019-10-10 12:31:58 -03003949 /*
3950 * When mounting SMB root file systems, we do not want to block in
3951 * connect. Otherwise bail out and then let cifs_reconnect() perform
3952 * reconnect failover - if possible.
3953 */
3954 if (server->noblockcnt && rc == -EINPROGRESS)
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003955 rc = 0;
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003956 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003957 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003958 sock_release(socket);
3959 server->ssocket = NULL;
3960 return rc;
3961 }
3962
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003963 if (sport == htons(RFC1001_PORT))
3964 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003965
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 return rc;
3967}
3968
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003969static int
3970ip_connect(struct TCP_Server_Info *server)
3971{
Steve French6da97912011-03-13 18:55:55 +00003972 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003973 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3974 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3975
3976 if (server->dstaddr.ss_family == AF_INET6)
3977 sport = &addr6->sin6_port;
3978 else
3979 sport = &addr->sin_port;
3980
3981 if (*sport == 0) {
3982 int rc;
3983
3984 /* try with 445 port at first */
3985 *sport = htons(CIFS_PORT);
3986
3987 rc = generic_ip_connect(server);
3988 if (rc >= 0)
3989 return rc;
3990
3991 /* if it failed, try with 139 port */
3992 *sport = htons(RFC1001_PORT);
3993 }
3994
3995 return generic_ip_connect(server);
3996}
3997
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003998void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003999 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00004000{
4001 /* if we are reconnecting then should we check to see if
4002 * any requested capabilities changed locally e.g. via
4003 * remount but we can not do much about it here
4004 * if they have (even if we could detect it by the following)
4005 * Perhaps we could add a backpointer to array of sb from tcon
4006 * or if we change to make all sb to same share the same
4007 * sb as NFS - then we only have one backpointer to sb.
4008 * What if we wanted to mount the server share twice once with
4009 * and once without posixacls or posix paths? */
4010 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00004011
Steve Frenchc18c8422007-07-18 23:21:09 +00004012 if (vol_info && vol_info->no_linux_ext) {
4013 tcon->fsUnixInfo.Capability = 0;
4014 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05004015 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004016 return;
4017 } else if (vol_info)
4018 tcon->unix_ext = 1; /* Unix Extensions supported */
4019
4020 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004021 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004022 return;
4023 }
Steve French50c2f752007-07-13 00:33:32 +00004024
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004025 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00004026 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05004027 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00004028 /* check for reconnect case in which we do not
4029 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004030 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004031 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00004032 originally at mount time */
4033 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
4034 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004035 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
4036 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004037 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00004038 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004039 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004040 cifs_dbg(VFS, "possible reconnect error\n");
4041 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00004042 }
Steve French8af18972007-02-14 04:42:51 +00004043 }
Steve French50c2f752007-07-13 00:33:32 +00004044
Steve French6848b732011-05-26 18:38:54 +00004045 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004046 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00004047
Steve French8af18972007-02-14 04:42:51 +00004048 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00004049 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00004050 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004051 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004052 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004053 if (cifs_sb)
4054 cifs_sb->mnt_cifs_flags |=
4055 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00004056 }
4057
Steve French75865f8c2007-06-24 18:30:48 +00004058 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00004059 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004060 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004061 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004062 if (cifs_sb)
4063 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00004064 CIFS_MOUNT_POSIX_PATHS;
4065 }
Steve French50c2f752007-07-13 00:33:32 +00004066
Joe Perchesf96637b2013-05-04 22:12:25 -05004067 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00004068#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00004069 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004070 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004071 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004072 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004073 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004074 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004075 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004076 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004077 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004078 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004079 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004080 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004081 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004082 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00004083 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004084 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00004085 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004086 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00004087#endif /* CIFS_DEBUG2 */
4088 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00004089 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004090 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00004091 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05004092 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 +00004093
Steve French8af18972007-02-14 04:42:51 +00004094 }
4095 }
4096}
4097
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004098int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004099 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004100{
Jeff Layton2de970f2010-10-06 19:51:12 -04004101 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
4102
Al Viro2ced6f62011-06-17 09:20:04 -04004103 spin_lock_init(&cifs_sb->tlink_tree_lock);
4104 cifs_sb->tlink_tree = RB_ROOT;
4105
Steve Frenche8506d22019-02-28 21:32:15 -06004106 cifs_sb->bsize = pvolume_info->bsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004107 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004108 * Temporarily set r/wsize for matching superblock. If we end up using
4109 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004110 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004111 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004112 cifs_sb->wsize = pvolume_info->wsize;
4113
Steve French3b795212008-11-13 19:45:32 +00004114 cifs_sb->mnt_uid = pvolume_info->linux_uid;
4115 cifs_sb->mnt_gid = pvolume_info->linux_gid;
4116 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
4117 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Frank Sorensonf52aa792020-02-12 15:31:48 -06004118 cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05004119 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00004120
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304121 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004122 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304123
Aurelien Aptel83930722018-09-20 18:10:25 -07004124 if (pvolume_info->nodfs)
4125 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00004126 if (pvolume_info->noperm)
4127 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4128 if (pvolume_info->setuids)
4129 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05004130 if (pvolume_info->setuidfromacl)
4131 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00004132 if (pvolume_info->server_ino)
4133 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4134 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05004135 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
4136 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00004137 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4138 if (pvolume_info->no_xattr)
4139 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4140 if (pvolume_info->sfu_emul)
4141 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4142 if (pvolume_info->nobrl)
4143 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05004144 if (pvolume_info->nohandlecache)
4145 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00004146 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00004147 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00004148 if (pvolume_info->mand_lock)
4149 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00004150 if (pvolume_info->rwpidforward)
4151 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French412094a2019-06-24 02:01:42 -05004152 if (pvolume_info->mode_ace)
4153 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
Steve French3b795212008-11-13 19:45:32 +00004154 if (pvolume_info->cifs_acl)
4155 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004156 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004157 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004158 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
4159 }
4160 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004161 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004162 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
4163 }
Steve French3b795212008-11-13 19:45:32 +00004164 if (pvolume_info->override_uid)
4165 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
4166 if (pvolume_info->override_gid)
4167 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
4168 if (pvolume_info->dynperm)
4169 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05304170 if (pvolume_info->fsc)
4171 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04004172 if (pvolume_info->multiuser)
4173 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
4174 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05004175 if (pvolume_info->strict_io)
4176 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00004177 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004178 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00004179 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
4180 }
Steve French83bbfa72019-08-27 23:58:54 -05004181 if (pvolume_info->cache_ro) {
4182 cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4183 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
Steve French41e033f2019-08-30 02:12:41 -05004184 } else if (pvolume_info->cache_rw) {
4185 cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4186 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4187 CIFS_MOUNT_RW_CACHE);
Steve French83bbfa72019-08-27 23:58:54 -05004188 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004189 if (pvolume_info->mfsymlinks) {
4190 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05004191 /*
4192 * Our SFU ("Services for Unix" emulation does not allow
4193 * creating symlinks but does allow reading existing SFU
4194 * symlinks (it does allow both creating and reading SFU
4195 * style mknod and FIFOs though). When "mfsymlinks" and
4196 * "sfu" are both enabled at the same time, it allows
4197 * reading both types of symlinks, but will only create
4198 * them with mfsymlinks format. This allows better
4199 * Apple compatibility (probably better for Samba too)
4200 * while still recognizing old Windows style symlinks.
4201 */
4202 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004203 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05004204 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004205 }
Steve French3b795212008-11-13 19:45:32 +00004206
4207 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05004208 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004209
4210 if (pvolume_info->prepath) {
4211 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
4212 if (cifs_sb->prepath == NULL)
4213 return -ENOMEM;
4214 }
4215
4216 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004217}
4218
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004219void
4220cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004221{
Sean Finneyb9468452011-04-11 13:19:32 +00004222 kfree(volume_info->username);
Waiman Long453431a2020-08-06 23:18:13 -07004223 kfree_sensitive(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02004224 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00004225 kfree(volume_info->domainname);
4226 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004227 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004228}
4229
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004230void
4231cifs_cleanup_volume_info(struct smb_vol *volume_info)
4232{
4233 if (!volume_info)
4234 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004235 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004236 kfree(volume_info);
4237}
4238
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004239/* Release all succeed connections */
4240static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4241 unsigned int xid,
4242 struct TCP_Server_Info *server,
4243 struct cifs_ses *ses, struct cifs_tcon *tcon)
4244{
4245 int rc = 0;
4246
4247 if (tcon)
4248 cifs_put_tcon(tcon);
4249 else if (ses)
4250 cifs_put_smb_ses(ses);
4251 else if (server)
4252 cifs_put_tcp_session(server, 0);
4253 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4254 free_xid(xid);
4255}
4256
4257/* Get connections for tcp, ses and tcon */
4258static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4259 unsigned int *xid,
4260 struct TCP_Server_Info **nserver,
4261 struct cifs_ses **nses, struct cifs_tcon **ntcon)
4262{
4263 int rc = 0;
4264 struct TCP_Server_Info *server;
4265 struct cifs_ses *ses;
4266 struct cifs_tcon *tcon;
4267
4268 *nserver = NULL;
4269 *nses = NULL;
4270 *ntcon = NULL;
4271
4272 *xid = get_xid();
4273
4274 /* get a reference to a tcp session */
4275 server = cifs_get_tcp_session(vol);
4276 if (IS_ERR(server)) {
4277 rc = PTR_ERR(server);
4278 return rc;
4279 }
4280
4281 *nserver = server;
4282
4283 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
4284 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4285 else
4286 server->max_credits = vol->max_credits;
4287
4288 /* get a reference to a SMB session */
4289 ses = cifs_get_smb_ses(server, vol);
4290 if (IS_ERR(ses)) {
4291 rc = PTR_ERR(ses);
4292 return rc;
4293 }
4294
4295 *nses = ses;
4296
4297 if ((vol->persistent == true) && (!(ses->server->capabilities &
4298 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004299 cifs_server_dbg(VFS, "persistent handles not supported by server\n");
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004300 return -EOPNOTSUPP;
4301 }
4302
4303 /* search for existing tcon to this server share */
4304 tcon = cifs_get_tcon(ses, vol);
4305 if (IS_ERR(tcon)) {
4306 rc = PTR_ERR(tcon);
4307 return rc;
4308 }
4309
4310 *ntcon = tcon;
4311
4312 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4313 if (tcon->posix_extensions)
4314 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4315
4316 /* tell server which Unix caps we support */
4317 if (cap_unix(tcon->ses)) {
4318 /*
4319 * reset of caps checks mount to see if unix extensions disabled
4320 * for just this mount.
4321 */
4322 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4323 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4324 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4325 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4326 return -EACCES;
4327 } else
4328 tcon->unix_ext = 0; /* server does not support them */
4329
4330 /* do not care if a following call succeed - informational */
Steve French1981eba2019-08-29 22:33:38 -05004331 if (!tcon->pipe && server->ops->qfs_tcon) {
Amir Goldstein0f060932020-02-03 21:46:43 +02004332 server->ops->qfs_tcon(*xid, tcon, cifs_sb);
Steve French1981eba2019-08-29 22:33:38 -05004333 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4334 if (tcon->fsDevInfo.DeviceCharacteristics &
Steve French52870d52019-10-01 21:25:46 -05004335 cpu_to_le32(FILE_READ_ONLY_DEVICE))
Steve French1981eba2019-08-29 22:33:38 -05004336 cifs_dbg(VFS, "mounted to read only share\n");
Steve French41e033f2019-08-30 02:12:41 -05004337 else if ((cifs_sb->mnt_cifs_flags &
4338 CIFS_MOUNT_RW_CACHE) == 0)
Steve French1981eba2019-08-29 22:33:38 -05004339 cifs_dbg(VFS, "read only mount of RW share\n");
Steve French41e033f2019-08-30 02:12:41 -05004340 /* no need to log a RW mount of a typical RW share */
Steve French1981eba2019-08-29 22:33:38 -05004341 }
4342 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004343
4344 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4345 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4346
4347 return 0;
4348}
4349
4350static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4351 struct cifs_tcon *tcon)
4352{
4353 struct tcon_link *tlink;
4354
4355 /* hang the tcon off of the superblock */
4356 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4357 if (tlink == NULL)
4358 return -ENOMEM;
4359
4360 tlink->tl_uid = ses->linux_uid;
4361 tlink->tl_tcon = tcon;
4362 tlink->tl_time = jiffies;
4363 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4364 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4365
4366 cifs_sb->master_tlink = tlink;
4367 spin_lock(&cifs_sb->tlink_tree_lock);
4368 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4369 spin_unlock(&cifs_sb->tlink_tree_lock);
4370
4371 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4372 TLINK_IDLE_EXPIRE);
4373 return 0;
4374}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004375
Steve French2d6d5892009-04-09 00:36:44 +00004376#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004377/*
4378 * cifs_build_path_to_root returns full path to root when we do not have an
4379 * exiting connection (tcon)
4380 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004381static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004382build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004383 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004384{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004385 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004386 unsigned int pplen = useppath && vol->prepath ?
4387 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004388 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004389
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004390 if (unc_len > MAX_TREE_SIZE)
4391 return ERR_PTR(-EINVAL);
4392
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004393 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004394 if (full_path == NULL)
4395 return ERR_PTR(-ENOMEM);
4396
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004397 memcpy(full_path, vol->UNC, unc_len);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004398 pos = full_path + unc_len;
4399
4400 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004401 *pos = CIFS_DIR_SEP(cifs_sb);
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004402 memcpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004403 pos += pplen;
4404 }
4405
4406 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004407 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004408 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004409 return full_path;
4410}
Sean Finneydd613942011-04-11 13:19:30 +00004411
Paulo Alcantara1c780222018-11-14 16:24:03 -02004412/**
4413 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4414 *
Sean Finneydd613942011-04-11 13:19:30 +00004415 *
Sean Finney046462a2011-04-11 13:19:33 +00004416 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4417 * to a string containing updated options for the submount. Otherwise it
4418 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004419 *
4420 * Returns the rc from get_dfs_path to the caller, which can be used to
4421 * determine whether there were referrals.
4422 */
4423static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004424expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004425 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004426 char *ref_path)
Sean Finneydd613942011-04-11 13:19:30 +00004427{
4428 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004429 struct dfs_info3_param referral = {0};
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004430 char *full_path = NULL, *mdata = NULL;
Sean Finneydd613942011-04-11 13:19:30 +00004431
Aurelien Aptel83930722018-09-20 18:10:25 -07004432 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4433 return -EREMOTE;
4434
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004435 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004436 if (IS_ERR(full_path))
4437 return PTR_ERR(full_path);
4438
Paulo Alcantara1c780222018-11-14 16:24:03 -02004439 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4440 ref_path, &referral, NULL);
4441 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004442 char *fake_devname = NULL;
4443
4444 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004445 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004446 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004447 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004448
Sean Finneydd613942011-04-11 13:19:30 +00004449 if (IS_ERR(mdata)) {
4450 rc = PTR_ERR(mdata);
4451 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004452 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004453 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004454 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004455 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004456 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004457 kfree(fake_devname);
4458 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004459 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004460 }
4461 kfree(full_path);
4462 return rc;
4463}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004464
4465static inline int get_next_dfs_tgt(const char *path,
4466 struct dfs_cache_tgt_list *tgt_list,
4467 struct dfs_cache_tgt_iterator **tgt_it)
4468{
4469 if (!*tgt_it)
4470 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4471 else
4472 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4473 return !*tgt_it ? -EHOSTDOWN : 0;
4474}
4475
4476static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4477 struct smb_vol *fake_vol, struct smb_vol *vol)
4478{
4479 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4480 int len = strlen(tgt) + 2;
4481 char *new_unc;
4482
4483 new_unc = kmalloc(len, GFP_KERNEL);
4484 if (!new_unc)
4485 return -ENOMEM;
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +10004486 scnprintf(new_unc, len, "\\%s", tgt);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004487
4488 kfree(vol->UNC);
4489 vol->UNC = new_unc;
4490
4491 if (fake_vol->prepath) {
4492 kfree(vol->prepath);
4493 vol->prepath = fake_vol->prepath;
4494 fake_vol->prepath = NULL;
4495 }
4496 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4497
4498 return 0;
4499}
4500
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004501static int setup_dfs_tgt_conn(const char *path, const char *full_path,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004502 const struct dfs_cache_tgt_iterator *tgt_it,
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004503 struct cifs_sb_info *cifs_sb, struct smb_vol *vol, unsigned int *xid,
4504 struct TCP_Server_Info **server, struct cifs_ses **ses,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004505 struct cifs_tcon **tcon)
4506{
4507 int rc;
4508 struct dfs_info3_param ref = {0};
4509 char *mdata = NULL, *fake_devname = NULL;
Steve Frenchd0959b02019-10-05 10:53:58 -05004510 struct smb_vol fake_vol = {NULL};
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004511
4512 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4513
4514 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4515 if (rc)
4516 return rc;
4517
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004518 mdata = cifs_compose_mount_options(cifs_sb->mountdata, full_path + 1, &ref, &fake_devname);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004519 free_dfs_info_param(&ref);
4520
4521 if (IS_ERR(mdata)) {
4522 rc = PTR_ERR(mdata);
4523 mdata = NULL;
4524 } else {
4525 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4526 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4527 false);
4528 }
4529 kfree(mdata);
4530 kfree(fake_devname);
4531
4532 if (!rc) {
4533 /*
4534 * We use a 'fake_vol' here because we need pass it down to the
4535 * mount_{get,put} functions to test connection against new DFS
4536 * targets.
4537 */
4538 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4539 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4540 tcon);
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004541 if (!rc || (*server && *ses)) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004542 /*
4543 * We were able to connect to new target server.
4544 * Update current volume info with new target server.
4545 */
4546 rc = update_vol_info(tgt_it, &fake_vol, vol);
4547 }
4548 }
4549 cifs_cleanup_volume_info_contents(&fake_vol);
4550 return rc;
4551}
4552
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004553static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb,
4554 struct smb_vol *vol, struct cifs_ses *root_ses, unsigned int *xid,
4555 struct TCP_Server_Info **server, struct cifs_ses **ses,
4556 struct cifs_tcon **tcon)
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004557{
4558 int rc;
4559 struct dfs_cache_tgt_list tgt_list;
4560 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4561
4562 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4563 return -EOPNOTSUPP;
4564
4565 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4566 if (rc)
4567 return rc;
4568
4569 for (;;) {
4570 /* Get next DFS target server - if any */
4571 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4572 if (rc)
4573 break;
4574 /* Connect to next DFS target */
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004575 rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, vol, xid, server, ses,
4576 tcon);
4577 if (!rc || (*server && *ses))
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004578 break;
4579 }
4580 if (!rc) {
4581 /*
4582 * Update DFS target hint in DFS referral cache with the target
4583 * server we successfully reconnected to.
4584 */
4585 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4586 cifs_sb->local_nls,
4587 cifs_remap(cifs_sb), path,
4588 tgt_it);
4589 }
4590 dfs_cache_free_tgts(&tgt_list);
4591 return rc;
4592}
Steve French2d6d5892009-04-09 00:36:44 +00004593#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004594
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004595int
Jeff Layton04db79b2011-07-06 08:10:38 -04004596cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004597 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004599 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004600
Steve Frenchc7c137b2018-06-06 17:59:29 -05004601 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004602 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603
Jeff Layton7586b762008-12-01 18:41:49 -05004604 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004605 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004606 kfree(volume_info->username);
4607 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004608 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004610 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004612 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004613 /* In userspace mount helper we can get user name from alternate
4614 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004615 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 }
4617
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004619 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004620 /* load_nls_default cannot return null */
4621 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004623 volume_info->local_nls = load_nls(volume_info->iocharset);
4624 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004625 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004626 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004627 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 }
4629 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004630
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004631 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004632}
4633
4634struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004635cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004636{
4637 int rc;
4638 struct smb_vol *volume_info;
4639
Jeff Layton6ee95422012-11-26 11:09:57 -05004640 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004641 if (!volume_info)
4642 return ERR_PTR(-ENOMEM);
4643
Steve Frenchc7c137b2018-06-06 17:59:29 -05004644 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004645 if (rc) {
4646 cifs_cleanup_volume_info(volume_info);
4647 volume_info = ERR_PTR(rc);
4648 }
4649
4650 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004651}
4652
Aurelien Aptela6b50582016-05-25 19:59:09 +02004653static int
4654cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4655 unsigned int xid,
4656 struct cifs_tcon *tcon,
4657 struct cifs_sb_info *cifs_sb,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004658 char *full_path,
4659 int added_treename)
Aurelien Aptela6b50582016-05-25 19:59:09 +02004660{
4661 int rc;
4662 char *s;
4663 char sep, tmp;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004664 int skip = added_treename ? 1 : 0;
Aurelien Aptela6b50582016-05-25 19:59:09 +02004665
4666 sep = CIFS_DIR_SEP(cifs_sb);
4667 s = full_path;
4668
4669 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4670 while (rc == 0) {
4671 /* skip separators */
4672 while (*s == sep)
4673 s++;
4674 if (!*s)
4675 break;
4676 /* next separator */
4677 while (*s && *s != sep)
4678 s++;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004679 /*
4680 * if the treename is added, we then have to skip the first
4681 * part within the separators
4682 */
4683 if (skip) {
4684 skip = 0;
4685 continue;
4686 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004687 /*
4688 * temporarily null-terminate the path at the end of
4689 * the current component
4690 */
4691 tmp = *s;
4692 *s = 0;
4693 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4694 full_path);
4695 *s = tmp;
4696 }
4697 return rc;
4698}
4699
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004700/*
4701 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4702 * otherwise 0.
4703 */
4704static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4705 const unsigned int xid,
4706 struct TCP_Server_Info *server,
4707 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004708{
Jeff Layton1daaae82012-03-21 06:30:40 -04004709 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004710 char *full_path;
4711
4712 if (!server->ops->is_path_accessible)
4713 return -EOPNOTSUPP;
4714
4715 /*
4716 * cifs_build_path_to_root works only when we have a valid tcon
4717 */
4718 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4719 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4720 if (full_path == NULL)
4721 return -ENOMEM;
4722
4723 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4724
4725 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4726 full_path);
4727 if (rc != 0 && rc != -EREMOTE) {
4728 kfree(full_path);
4729 return rc;
4730 }
4731
4732 if (rc != -EREMOTE) {
4733 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004734 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004735 if (rc != 0) {
Joe Perchesa0a30362020-04-14 22:42:53 -07004736 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 -02004737 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4738 rc = 0;
4739 }
4740 }
4741
4742 kfree(full_path);
4743 return rc;
4744}
4745
4746#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004747static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4748 struct cifs_ses **root_ses)
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004749{
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004750 if (ses) {
4751 spin_lock(&cifs_tcp_ses_lock);
4752 ses->ses_count++;
4753 ses->tcon_ipc->remap = cifs_remap(cifs_sb);
4754 spin_unlock(&cifs_tcp_ses_lock);
4755 }
4756 *root_ses = ses;
4757}
4758
4759static void put_root_ses(struct cifs_ses *ses)
4760{
4761 if (ses)
4762 cifs_put_smb_ses(ses);
4763}
4764
4765/* Check if a path component is remote and then update @dfs_path accordingly */
4766static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4767 const unsigned int xid, struct TCP_Server_Info *server,
4768 struct cifs_tcon *tcon, char **dfs_path)
4769{
4770 char *path, *s;
4771 char sep = CIFS_DIR_SEP(cifs_sb), tmp;
4772 char *npath;
4773 int rc = 0;
4774 int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS;
4775 int skip = added_treename;
4776
4777 path = cifs_build_path_to_root(vol, cifs_sb, tcon, added_treename);
4778 if (!path)
4779 return -ENOMEM;
4780
4781 /*
4782 * Walk through the path components in @path and check if they're accessible. In case any of
4783 * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path
4784 * (NOT including the remaining components).
4785 */
4786 s = path;
4787 do {
4788 /* skip separators */
4789 while (*s && *s == sep)
4790 s++;
4791 if (!*s)
4792 break;
4793 /* next separator */
4794 while (*s && *s != sep)
4795 s++;
4796 /*
4797 * if the treename is added, we then have to skip the first
4798 * part within the separators
4799 */
4800 if (skip) {
4801 skip = 0;
4802 continue;
4803 }
4804 tmp = *s;
4805 *s = 0;
4806 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path);
4807 if (rc && rc == -EREMOTE) {
4808 struct smb_vol v = {NULL};
4809 /* if @path contains a tree name, skip it in the prefix path */
4810 if (added_treename) {
4811 rc = cifs_parse_devname(path, &v);
4812 if (rc)
4813 break;
4814 rc = -EREMOTE;
4815 npath = build_unc_path_to_root(&v, cifs_sb, true);
4816 cifs_cleanup_volume_info_contents(&v);
4817 } else {
4818 v.UNC = vol->UNC;
4819 v.prepath = path + 1;
4820 npath = build_unc_path_to_root(&v, cifs_sb, true);
4821 }
4822 if (IS_ERR(npath)) {
4823 rc = PTR_ERR(npath);
4824 break;
4825 }
4826 kfree(*dfs_path);
4827 *dfs_path = npath;
4828 }
4829 *s = tmp;
4830 } while (rc == 0);
4831
4832 kfree(path);
4833 return rc;
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004834}
4835
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004836int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4837{
4838 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004839 unsigned int xid;
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004840 struct TCP_Server_Info *server = NULL;
4841 struct cifs_ses *ses = NULL, *root_ses = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004842 struct cifs_tcon *tcon = NULL;
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004843 int count = 0;
4844 char *ref_path = NULL, *full_path = NULL;
4845 char *oldmnt = NULL;
4846 char *mntdata = NULL;
Al Virodd854462011-06-17 08:24:42 -04004847
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004848 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004849 /*
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004850 * Unconditionally try to get an DFS referral (even cached) to determine whether it is an
4851 * DFS mount.
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004852 *
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004853 * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem
4854 * to respond with PATH_NOT_COVERED to requests that include the prefix.
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004855 */
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004856 if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4857 NULL)) {
4858 /* No DFS referral was returned. Looks like a regular share. */
4859 if (rc)
4860 goto error;
4861 /* Check if it is fully accessible and then mount it */
4862 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4863 if (!rc)
4864 goto out;
4865 if (rc != -EREMOTE)
4866 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004867 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004868 /* Save mount options */
4869 mntdata = kstrndup(cifs_sb->mountdata, strlen(cifs_sb->mountdata), GFP_KERNEL);
4870 if (!mntdata) {
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004871 rc = -ENOMEM;
4872 goto error;
4873 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004874 /* Get path of DFS root */
4875 ref_path = build_unc_path_to_root(vol, cifs_sb, false);
4876 if (IS_ERR(ref_path)) {
4877 rc = PTR_ERR(ref_path);
4878 ref_path = NULL;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004879 goto error;
4880 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004881
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004882 set_root_ses(cifs_sb, ses, &root_ses);
4883 do {
4884 /* Save full path of last DFS path we used to resolve final target server */
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004885 kfree(full_path);
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004886 full_path = build_unc_path_to_root(vol, cifs_sb, !!count);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004887 if (IS_ERR(full_path)) {
4888 rc = PTR_ERR(full_path);
Dan Carpenter20b135e2020-08-05 12:52:07 +03004889 full_path = NULL;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004890 break;
4891 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004892 /* Chase referral */
4893 oldmnt = cifs_sb->mountdata;
4894 rc = expand_dfs_referral(xid, root_ses, vol, cifs_sb, ref_path + 1);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004895 if (rc)
4896 break;
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004897 /* Connect to new DFS target only if we were redirected */
4898 if (oldmnt != cifs_sb->mountdata) {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004899 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004900 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004901 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004902 if (rc && !server && !ses) {
4903 /* Failed to connect. Try to connect to other targets in the referral. */
4904 rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, vol, root_ses, &xid,
4905 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004906 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004907 if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses)
4908 break;
4909 if (!tcon)
4910 continue;
4911 /* Make sure that requests go through new root servers */
Paulo Alcantarae1837852020-08-27 11:20:19 -03004912 if (is_tcon_dfs(tcon)) {
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004913 put_root_ses(root_ses);
4914 set_root_ses(cifs_sb, ses, &root_ses);
4915 }
4916 /* Check for remaining path components and then continue chasing them (-EREMOTE) */
4917 rc = check_dfs_prepath(cifs_sb, vol, xid, server, tcon, &ref_path);
4918 /* Prevent recursion on broken link referrals */
4919 if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS)
4920 rc = -ELOOP;
4921 } while (rc == -EREMOTE);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004922
Jeff Layton9d002df2010-10-06 19:51:11 -04004923 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004924 goto error;
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004925 put_root_ses(root_ses);
4926 root_ses = NULL;
4927 kfree(ref_path);
4928 ref_path = NULL;
4929 /*
4930 * Store DFS full path in both superblock and tree connect structures.
4931 *
4932 * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so
4933 * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS
4934 * links, the prefix path is included in both and may be changed during reconnect. See
4935 * cifs_tree_connect().
4936 */
4937 cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004938 if (!cifs_sb->origin_fullpath) {
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004939 rc = -ENOMEM;
4940 goto error;
4941 }
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004942 spin_lock(&cifs_tcp_ses_lock);
4943 tcon->dfs_path = full_path;
4944 full_path = NULL;
4945 tcon->remap = cifs_remap(cifs_sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004946 spin_unlock(&cifs_tcp_ses_lock);
4947
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004948 /* Add original volume information for DFS cache to be used when refreshing referrals */
4949 rc = dfs_cache_add_vol(mntdata, vol, cifs_sb->origin_fullpath);
4950 if (rc)
Paulo Alcantarae511d312018-11-14 17:16:44 -02004951 goto error;
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004952 /*
4953 * After reconnecting to a different server, unique ids won't
4954 * match anymore, so we disable serverino. This prevents
4955 * dentry revalidation to think the dentry are stale (ESTALE).
4956 */
4957 cifs_autodisable_serverino(cifs_sb);
Paulo Alcantara (SUSE)bacd7042020-02-20 19:49:34 -03004958 /*
4959 * Force the use of prefix path to support failover on DFS paths that
4960 * resolve to targets that have different prefix paths.
4961 */
4962 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4963 kfree(cifs_sb->prepath);
4964 cifs_sb->prepath = vol->prepath;
4965 vol->prepath = NULL;
4966
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004967out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004968 free_xid(xid);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02004969 cifs_try_adding_channels(ses);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004970 return mount_setup_tlink(cifs_sb, ses, tcon);
4971
4972error:
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004973 kfree(ref_path);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004974 kfree(full_path);
Paulo Alcantara7efd0812020-07-21 09:36:44 -03004975 kfree(mntdata);
4976 kfree(cifs_sb->origin_fullpath);
4977 put_root_ses(root_ses);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004978 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004979 return rc;
4980}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004981#else
4982int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4983{
4984 int rc = 0;
4985 unsigned int xid;
4986 struct cifs_ses *ses;
4987 struct cifs_tcon *tcon;
4988 struct TCP_Server_Info *server;
4989
4990 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4991 if (rc)
4992 goto error;
4993
4994 if (tcon) {
4995 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4996 if (rc == -EREMOTE)
4997 rc = -EOPNOTSUPP;
4998 if (rc)
4999 goto error;
5000 }
5001
5002 free_xid(xid);
5003
5004 return mount_setup_tlink(cifs_sb, ses, tcon);
5005
5006error:
5007 mount_put_conns(cifs_sb, xid, server, ses, tcon);
5008 return rc;
5009}
5010#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005011
Jeff Layton8d1bca32011-06-11 21:17:10 -04005012/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01005013 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04005014 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005015int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04005016CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00005017 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 const struct nls_table *nls_codepage)
5019{
5020 struct smb_hdr *smb_buffer;
5021 struct smb_hdr *smb_buffer_response;
5022 TCONX_REQ *pSMB;
5023 TCONX_RSP *pSMBr;
5024 unsigned char *bcc_ptr;
5025 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05005026 int length;
5027 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028
5029 if (ses == NULL)
5030 return -EIO;
5031
5032 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00005033 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00005035
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036 smb_buffer_response = smb_buffer;
5037
5038 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
5039 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07005040
Pavel Shilovsky88257362012-05-23 14:01:59 +04005041 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042 smb_buffer->Uid = ses->Suid;
5043 pSMB = (TCONX_REQ *) smb_buffer;
5044 pSMBr = (TCONX_RSP *) smb_buffer_response;
5045
5046 pSMB->AndXCommand = 0xFF;
5047 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01005049 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08005050 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00005051 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08005052 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00005053 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08005054 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005055 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08005056 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
5057 specified as required (when that support is added to
5058 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00005059 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08005060 by Samba (not sure whether other servers allow
5061 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00005062#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04005063 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05005064 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05005065 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00005066 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05005067 SECMODE_PW_ENCRYPT ? true : false,
5068 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00005069 else
5070#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06005071 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05005072 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05005073 if (rc) {
5074 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
5075 __func__, rc);
5076 cifs_buf_release(smb_buffer);
5077 return rc;
5078 }
Steve Frencheeac8042006-01-13 21:34:58 -08005079
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005080 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005081 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00005082 /* must align unicode strings */
5083 *bcc_ptr = 0; /* null byte password */
5084 bcc_ptr++;
5085 }
Steve Frencheeac8042006-01-13 21:34:58 -08005086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087
Jeff Layton38d77c52013-05-26 07:01:00 -04005088 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005089 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
5090
5091 if (ses->capabilities & CAP_STATUS32) {
5092 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
5093 }
5094 if (ses->capabilities & CAP_DFS) {
5095 smb_buffer->Flags2 |= SMBFLG2_DFS;
5096 }
5097 if (ses->capabilities & CAP_UNICODE) {
5098 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
5099 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06005100 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00005101 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00005102 (/* server len*/ + 256 /* share len */), nls_codepage);
5103 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005104 bcc_ptr += 2; /* skip trailing null */
5105 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005106 strcpy(bcc_ptr, tree);
5107 bcc_ptr += strlen(tree) + 1;
5108 }
5109 strcpy(bcc_ptr, "?????");
5110 bcc_ptr += strlen("?????");
5111 bcc_ptr += 1;
5112 count = bcc_ptr - &pSMB->Password[0];
Qinglang Miao1a0e7f72020-07-25 16:56:01 +08005113 be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114 pSMB->ByteCount = cpu_to_le16(count);
5115
Steve French133672e2007-11-13 22:41:37 +00005116 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05005117 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01005120 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00005121 bool is_unicode;
5122
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00005124 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125 tcon->tid = smb_buffer_response->Tid;
5126 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05005127 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005128 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00005129 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
5130 is_unicode = true;
5131 else
5132 is_unicode = false;
5133
Jeff Laytoncc20c032009-04-30 07:16:21 -04005134
Steve French50c2f752007-07-13 00:33:32 +00005135 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00005136 if (length == 3) {
5137 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
5138 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05005139 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01005140 tcon->ipc = true;
5141 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00005142 }
5143 } else if (length == 2) {
5144 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
5145 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05005146 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00005147 }
5148 }
Steve French50c2f752007-07-13 00:33:32 +00005149 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04005150 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05005151 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04005152
5153 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04005154 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06005155 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00005156 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04005157 nls_codepage);
5158
Joe Perchesf96637b2013-05-04 22:12:25 -05005159 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005160
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005161 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00005162 (smb_buffer_response->WordCount == 7))
5163 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00005164 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
5165 else
5166 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05005167 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005168 }
5169
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00005170 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005171 return rc;
5172}
5173
Al Viro2e32cf52013-10-03 12:53:37 -04005174static void delayed_free(struct rcu_head *p)
5175{
5176 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
5177 unload_nls(sbi->local_nls);
5178 kfree(sbi);
5179}
5180
Al Viro2a9b9952011-06-17 09:27:16 -04005181void
5182cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005183{
Jeff Laytonb647c352010-10-28 11:16:44 -04005184 struct rb_root *root = &cifs_sb->tlink_tree;
5185 struct rb_node *node;
5186 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187
Jeff Layton2de970f2010-10-06 19:51:12 -04005188 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
5189
Jeff Laytonb647c352010-10-28 11:16:44 -04005190 spin_lock(&cifs_sb->tlink_tree_lock);
5191 while ((node = rb_first(root))) {
5192 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5193 cifs_get_tlink(tlink);
5194 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5195 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00005196
Jeff Laytonb647c352010-10-28 11:16:44 -04005197 spin_unlock(&cifs_sb->tlink_tree_lock);
5198 cifs_put_tlink(tlink);
5199 spin_lock(&cifs_sb->tlink_tree_lock);
5200 }
5201 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005202
Al Virod757d712011-06-17 09:42:43 -04005203 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02005204 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005205#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02005206 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005207 kfree(cifs_sb->origin_fullpath);
5208#endif
Al Viro2e32cf52013-10-03 12:53:37 -04005209 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00005210}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005212int
5213cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005214{
5215 int rc = 0;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005216 struct TCP_Server_Info *server = cifs_ses_server(ses);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005218 if (!server->ops->need_neg || !server->ops->negotiate)
5219 return -ENOSYS;
5220
Jeff Layton198b5682010-04-24 07:57:48 -04005221 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005222 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04005223 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005225 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005226 if (rc == 0) {
5227 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04005228 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04005229 server->tcpStatus = CifsGood;
5230 else
5231 rc = -EHOSTDOWN;
5232 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005233 }
Steve French26b994f2008-08-06 05:11:33 +00005234
Jeff Layton198b5682010-04-24 07:57:48 -04005235 return rc;
5236}
Steve French26b994f2008-08-06 05:11:33 +00005237
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005238int
5239cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
5240 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04005241{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005242 int rc = -ENOSYS;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005243 struct TCP_Server_Info *server = cifs_ses_server(ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005244
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02005245 if (!ses->binding) {
5246 ses->capabilities = server->capabilities;
5247 if (linuxExtEnabled == 0)
5248 ses->capabilities &= (~server->vals->cap_unix);
5249
5250 if (ses->auth_key.response) {
5251 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
5252 ses->auth_key.response);
5253 kfree(ses->auth_key.response);
5254 ses->auth_key.response = NULL;
5255 ses->auth_key.len = 0;
5256 }
5257 }
Steve French20418ac2009-04-30 16:13:32 +00005258
Joe Perchesf96637b2013-05-04 22:12:25 -05005259 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00005260 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04005261
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005262 if (server->ops->sess_setup)
5263 rc = server->ops->sess_setup(xid, ses, nls_info);
5264
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05005265 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10005266 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05005267
Linus Torvalds1da177e2005-04-16 15:20:36 -07005268 return rc;
5269}
5270
Jeff Layton8a8798a2012-01-17 16:09:15 -05005271static int
5272cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
5273{
Jeff Layton3f618222013-06-12 19:52:14 -05005274 vol->sectype = ses->sectype;
5275
5276 /* krb5 is special, since we don't need username or pw */
5277 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05005278 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05005279
5280 return cifs_set_cifscreds(vol, ses);
5281}
5282
Steve French96daf2b2011-05-27 04:34:02 +00005283static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005284cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04005285{
Jeff Layton8a8798a2012-01-17 16:09:15 -05005286 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00005287 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
5288 struct cifs_ses *ses;
5289 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04005290 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04005291
5292 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03005293 if (vol_info == NULL)
5294 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04005295
Jeff Layton9d002df2010-10-06 19:51:11 -04005296 vol_info->local_nls = cifs_sb->local_nls;
5297 vol_info->linux_uid = fsuid;
5298 vol_info->cred_uid = fsuid;
5299 vol_info->UNC = master_tcon->treeName;
5300 vol_info->retry = master_tcon->retry;
5301 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05005302 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04005303 vol_info->local_lease = master_tcon->local_lease;
Paul Aurichad35f162020-06-26 12:58:07 -07005304 vol_info->no_lease = master_tcon->no_lease;
Paul Aurich00dfbc22020-06-26 12:58:06 -07005305 vol_info->resilient = master_tcon->use_resilient;
5306 vol_info->persistent = master_tcon->use_persistent;
Paul Aurich6b356f6c2020-06-26 12:58:08 -07005307 vol_info->handle_timeout = master_tcon->handle_timeout;
Jeff Layton9d002df2010-10-06 19:51:11 -04005308 vol_info->no_linux_ext = !master_tcon->unix_ext;
Paul Aurich5391b8e2020-06-26 12:58:09 -07005309 vol_info->linux_ext = master_tcon->posix_extensions;
Jeff Layton28e11bd2013-05-26 07:01:00 -04005310 vol_info->sectype = master_tcon->ses->sectype;
5311 vol_info->sign = master_tcon->ses->sign;
Paul Aurichcc154612020-06-26 12:58:05 -07005312 vol_info->seal = master_tcon->seal;
Jeff Layton9d002df2010-10-06 19:51:11 -04005313
Jeff Layton8a8798a2012-01-17 16:09:15 -05005314 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
5315 if (rc) {
5316 tcon = ERR_PTR(rc);
5317 goto out;
5318 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005319
5320 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305321 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005322 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305323 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005324
5325 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
5326 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00005327 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07005328 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04005329 goto out;
5330 }
5331
5332 tcon = cifs_get_tcon(ses, vol_info);
5333 if (IS_ERR(tcon)) {
5334 cifs_put_smb_ses(ses);
5335 goto out;
5336 }
5337
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005338 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04005339 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05005340
Jeff Layton9d002df2010-10-06 19:51:11 -04005341out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05005342 kfree(vol_info->username);
Waiman Long453431a2020-08-06 23:18:13 -07005343 kfree_sensitive(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005344 kfree(vol_info);
5345
5346 return tcon;
5347}
5348
Steve French96daf2b2011-05-27 04:34:02 +00005349struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005350cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5351{
5352 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5353}
5354
Jeff Laytonb647c352010-10-28 11:16:44 -04005355/* find and return a tlink with given uid */
5356static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005357tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005358{
5359 struct rb_node *node = root->rb_node;
5360 struct tcon_link *tlink;
5361
5362 while (node) {
5363 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5364
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005365 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005366 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005367 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005368 node = node->rb_right;
5369 else
5370 return tlink;
5371 }
5372 return NULL;
5373}
5374
5375/* insert a tcon_link into the tree */
5376static void
5377tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5378{
5379 struct rb_node **new = &(root->rb_node), *parent = NULL;
5380 struct tcon_link *tlink;
5381
5382 while (*new) {
5383 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5384 parent = *new;
5385
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005386 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005387 new = &((*new)->rb_left);
5388 else
5389 new = &((*new)->rb_right);
5390 }
5391
5392 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5393 rb_insert_color(&new_tlink->tl_rbnode, root);
5394}
5395
Jeff Layton9d002df2010-10-06 19:51:11 -04005396/*
5397 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5398 * current task.
5399 *
5400 * If the superblock doesn't refer to a multiuser mount, then just return
5401 * the master tcon for the mount.
5402 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305403 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005404 * exists, then check to see if it's pending construction. If it is then wait
5405 * for construction to complete. Once it's no longer pending, check to see if
5406 * it failed and either return an error or retry construction, depending on
5407 * the timeout.
5408 *
5409 * If one doesn't exist then insert a new tcon_link struct into the tree and
5410 * try to construct a new one.
5411 */
5412struct tcon_link *
5413cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5414{
5415 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005416 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005417 struct tcon_link *tlink, *newtlink;
5418
5419 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5420 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5421
5422 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005423 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005424 if (tlink)
5425 cifs_get_tlink(tlink);
5426 spin_unlock(&cifs_sb->tlink_tree_lock);
5427
5428 if (tlink == NULL) {
5429 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5430 if (newtlink == NULL)
5431 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005432 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005433 newtlink->tl_tcon = ERR_PTR(-EACCES);
5434 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5435 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5436 cifs_get_tlink(newtlink);
5437
Jeff Layton9d002df2010-10-06 19:51:11 -04005438 spin_lock(&cifs_sb->tlink_tree_lock);
5439 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005440 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005441 if (tlink) {
5442 cifs_get_tlink(tlink);
5443 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005444 kfree(newtlink);
5445 goto wait_for_construction;
5446 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005447 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005448 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5449 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005450 } else {
5451wait_for_construction:
5452 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005453 TASK_INTERRUPTIBLE);
5454 if (ret) {
5455 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005456 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005457 }
5458
5459 /* if it's good, return it */
5460 if (!IS_ERR(tlink->tl_tcon))
5461 return tlink;
5462
5463 /* return error if we tried this already recently */
5464 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5465 cifs_put_tlink(tlink);
5466 return ERR_PTR(-EACCES);
5467 }
5468
5469 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5470 goto wait_for_construction;
5471 }
5472
5473 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5474 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5475 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5476
5477 if (IS_ERR(tlink->tl_tcon)) {
5478 cifs_put_tlink(tlink);
5479 return ERR_PTR(-EACCES);
5480 }
5481
5482 return tlink;
5483}
Jeff Layton2de970f2010-10-06 19:51:12 -04005484
5485/*
5486 * periodic workqueue job that scans tcon_tree for a superblock and closes
5487 * out tcons.
5488 */
5489static void
5490cifs_prune_tlinks(struct work_struct *work)
5491{
5492 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5493 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005494 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005495 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005496 struct rb_node *tmp;
5497 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005498
Jeff Laytonb647c352010-10-28 11:16:44 -04005499 /*
5500 * Because we drop the spinlock in the loop in order to put the tlink
5501 * it's not guarded against removal of links from the tree. The only
5502 * places that remove entries from the tree are this function and
5503 * umounts. Because this function is non-reentrant and is canceled
5504 * before umount can proceed, this is safe.
5505 */
5506 spin_lock(&cifs_sb->tlink_tree_lock);
5507 node = rb_first(root);
5508 while (node != NULL) {
5509 tmp = node;
5510 node = rb_next(tmp);
5511 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5512
5513 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5514 atomic_read(&tlink->tl_count) != 0 ||
5515 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5516 continue;
5517
5518 cifs_get_tlink(tlink);
5519 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5520 rb_erase(tmp, root);
5521
Jeff Layton2de970f2010-10-06 19:51:12 -04005522 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005523 cifs_put_tlink(tlink);
5524 spin_lock(&cifs_sb->tlink_tree_lock);
5525 }
5526 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005527
Jeff Laytonda472fc2012-03-23 14:40:53 -04005528 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005529 TLINK_IDLE_EXPIRE);
5530}
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005531
5532#ifdef CONFIG_CIFS_DFS_UPCALL
5533int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
5534{
5535 int rc;
5536 struct TCP_Server_Info *server = tcon->ses->server;
5537 const struct smb_version_operations *ops = server->ops;
5538 struct dfs_cache_tgt_list tl;
5539 struct dfs_cache_tgt_iterator *it = NULL;
5540 char *tree;
5541 const char *tcp_host;
5542 size_t tcp_host_len;
5543 const char *dfs_host;
5544 size_t dfs_host_len;
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005545 char *share = NULL, *prefix = NULL;
Paulo Alcantara11375a52020-07-21 09:36:43 -03005546 struct dfs_info3_param ref = {0};
5547 bool isroot;
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005548
5549 tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
5550 if (!tree)
5551 return -ENOMEM;
5552
5553 if (!tcon->dfs_path) {
5554 if (tcon->ipc) {
5555 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
5556 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5557 } else {
5558 rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
5559 }
5560 goto out;
5561 }
5562
Paulo Alcantara11375a52020-07-21 09:36:43 -03005563 rc = dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005564 if (rc)
5565 goto out;
Paulo Alcantara11375a52020-07-21 09:36:43 -03005566 isroot = ref.server_type == DFS_TYPE_ROOT;
5567 free_dfs_info_param(&ref);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005568
5569 extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
5570
5571 for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) {
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005572 bool target_match;
5573
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005574 kfree(share);
5575 kfree(prefix);
Colin Ian Kingc6a80e12020-07-31 18:13:42 +01005576 share = NULL;
5577 prefix = NULL;
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005578
5579 rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005580 if (rc) {
5581 cifs_dbg(VFS, "%s: failed to parse target share %d\n",
5582 __func__, rc);
5583 continue;
5584 }
5585
5586 extract_unc_hostname(share, &dfs_host, &dfs_host_len);
5587
5588 if (dfs_host_len != tcp_host_len
5589 || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
5590 cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
5591 dfs_host, (int)tcp_host_len, tcp_host);
5592
5593 rc = match_target_ip(server, dfs_host, dfs_host_len, &target_match);
5594 if (rc) {
5595 cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
5596 break;
5597 }
5598
5599 if (!target_match) {
5600 cifs_dbg(FYI, "%s: skipping target\n", __func__);
5601 continue;
5602 }
5603 }
5604
5605 if (tcon->ipc) {
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005606 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005607 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5608 } else {
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005609 scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005610 rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
Paulo Alcantara11375a52020-07-21 09:36:43 -03005611 /* Only handle prefix paths of DFS link targets */
5612 if (!rc && !isroot) {
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005613 rc = update_super_prepath(tcon, prefix);
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005614 break;
5615 }
5616 }
5617 if (rc == -EREMOTE)
5618 break;
5619 }
5620
Paulo Alcantara7548e1d2020-07-21 09:36:42 -03005621 kfree(share);
5622 kfree(prefix);
5623
Stefan Metzmacher565674d2020-07-21 09:36:38 -03005624 if (!rc) {
5625 if (it)
5626 rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it);
5627 else
5628 rc = -ENOENT;
5629 }
5630 dfs_cache_free_tgts(&tl);
5631out:
5632 kfree(tree);
5633 return rc;
5634}
5635#else
5636int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
5637{
5638 const struct smb_version_operations *ops = tcon->ses->server->ops;
5639
5640 return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
5641}
5642#endif