blob: 86d1baedf21ca35d00337068a6d83125f15e6fab [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/connect.c
3 *
Steve French1080ef72011-02-24 18:07:19 +00004 * Copyright (C) International Business Machines Corp., 2002,2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
Steve Frenchfb8c4b12007-07-10 01:16:18 +000019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010024#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/list.h>
26#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090027#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/pagemap.h>
29#include <linux/ctype.h>
30#include <linux/utsname.h>
31#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070032#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070033#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000034#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070035#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080036#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040037#include <linux/namei.h>
Andrew Lunnc6e970a2017-03-28 23:45:06 +020038#include <linux/uuid.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080039#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040041#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040042#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050043#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000044#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040045#include <linux/parser.h>
Christoph Hellwig2f8b5442016-11-01 07:40:13 -060046#include <linux/bvec.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include "cifspdu.h"
48#include "cifsglob.h"
49#include "cifsproto.h"
50#include "cifs_unicode.h"
51#include "cifs_debug.h"
52#include "cifs_fs_sb.h"
53#include "ntlmssp.h"
54#include "nterr.h"
55#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053056#include "fscache.h"
Pavel Shilovsky53e0e112016-11-04 11:50:31 -070057#include "smb2proto.h"
Long Li2f894642017-11-22 17:38:34 -070058#include "smbdirect.h"
Paulo Alcantara1c780222018-11-14 16:24:03 -020059#include "dns_resolve.h"
Paulo Alcantara93d5cb52018-11-14 17:13:25 -020060#include "cifsfs.h"
Paulo Alcantara1c780222018-11-14 16:24:03 -020061#ifdef CONFIG_CIFS_DFS_UPCALL
62#include "dfs_cache.h"
63#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Linus Torvalds1da177e2005-04-16 15:20:36 -070065extern mempool_t *cifs_req_poolp;
Steve Frenchf92a7202018-05-24 04:11:07 -050066extern bool disable_legacy_dialects;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Jeff Layton2de970f2010-10-06 19:51:12 -040068/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040069#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040070#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040071
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040072enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040073 /* Mount options that take no arguments */
74 Opt_user_xattr, Opt_nouser_xattr,
75 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040076 Opt_forcegid, Opt_noforcegid,
Steve French3e7a02d2019-09-11 21:46:20 -050077 Opt_noblocksend, Opt_noautotune, Opt_nolease,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040078 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
Steve French2baa2682014-09-27 02:19:01 -050079 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040080 Opt_mapchars, Opt_nomapchars, Opt_sfu,
81 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
Steve Frenchb3266142018-05-20 23:41:10 -050082 Opt_noposixpaths, Opt_nounix, Opt_unix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040083 Opt_nocase,
84 Opt_brl, Opt_nobrl,
Steve French3d4ef9a2018-04-25 22:19:09 -050085 Opt_handlecache, Opt_nohandlecache,
Steve French95932652016-09-23 01:36:34 -050086 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040087 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
88 Opt_nohard, Opt_nosoft,
89 Opt_nointr, Opt_intr,
90 Opt_nostrictsync, Opt_strictsync,
91 Opt_serverino, Opt_noserverino,
92 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
93 Opt_acl, Opt_noacl, Opt_locallease,
Steve French4f5c10f2019-09-03 21:18:49 -050094 Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040095 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -040096 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -050097 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -060098 Opt_resilient, Opt_noresilient,
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -030099 Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200100 Opt_multichannel, Opt_nomultichannel,
Steve French9fe5ff12019-06-24 20:39:04 -0500101 Opt_compress,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400102
103 /* Mount options which take numeric value */
104 Opt_backupuid, Opt_backupgid, Opt_uid,
105 Opt_cruid, Opt_gid, Opt_file_mode,
106 Opt_dirmode, Opt_port,
Steve French563317e2019-09-08 23:22:02 -0500107 Opt_min_enc_offload,
Steve Frenche8506d22019-02-28 21:32:15 -0600108 Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
Steve Frenchca567eb2019-03-29 16:31:07 -0500109 Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200110 Opt_snapshot, Opt_max_channels,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400111
112 /* Mount options which take string value */
113 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400114 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400115 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400116 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400117
118 /* Mount options to be ignored */
119 Opt_ignore,
120
121 /* Options which could be blank */
122 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100123 Opt_blank_user,
124 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400125
126 Opt_err
127};
128
129static const match_table_t cifs_mount_option_tokens = {
130
131 { Opt_user_xattr, "user_xattr" },
132 { Opt_nouser_xattr, "nouser_xattr" },
133 { Opt_forceuid, "forceuid" },
134 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400135 { Opt_forcegid, "forcegid" },
136 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400137 { Opt_noblocksend, "noblocksend" },
138 { Opt_noautotune, "noautotune" },
Steve French3e7a02d2019-09-11 21:46:20 -0500139 { Opt_nolease, "nolease" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400140 { Opt_hard, "hard" },
141 { Opt_soft, "soft" },
142 { Opt_perm, "perm" },
143 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500144 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400145 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500146 { Opt_mapposix, "mapposix" }, /* SFM style */
147 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400148 { Opt_sfu, "sfu" },
149 { Opt_nosfu, "nosfu" },
150 { Opt_nodfs, "nodfs" },
151 { Opt_posixpaths, "posixpaths" },
152 { Opt_noposixpaths, "noposixpaths" },
153 { Opt_nounix, "nounix" },
154 { Opt_nounix, "nolinux" },
Steve Frenchb3266142018-05-20 23:41:10 -0500155 { Opt_nounix, "noposix" },
156 { Opt_unix, "unix" },
157 { Opt_unix, "linux" },
158 { Opt_unix, "posix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400159 { Opt_nocase, "nocase" },
160 { Opt_nocase, "ignorecase" },
161 { Opt_brl, "brl" },
162 { Opt_nobrl, "nobrl" },
Steve French3d4ef9a2018-04-25 22:19:09 -0500163 { Opt_handlecache, "handlecache" },
164 { Opt_nohandlecache, "nohandlecache" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400165 { Opt_nobrl, "nolock" },
166 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400167 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400168 { Opt_setuids, "setuids" },
169 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500170 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400171 { Opt_dynperm, "dynperm" },
172 { Opt_nodynperm, "nodynperm" },
173 { Opt_nohard, "nohard" },
174 { Opt_nosoft, "nosoft" },
175 { Opt_nointr, "nointr" },
176 { Opt_intr, "intr" },
177 { Opt_nostrictsync, "nostrictsync" },
178 { Opt_strictsync, "strictsync" },
179 { Opt_serverino, "serverino" },
180 { Opt_noserverino, "noserverino" },
181 { Opt_rwpidforward, "rwpidforward" },
Steve French412094a2019-06-24 02:01:42 -0500182 { Opt_modesid, "modefromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400183 { Opt_cifsacl, "cifsacl" },
184 { Opt_nocifsacl, "nocifsacl" },
185 { Opt_acl, "acl" },
186 { Opt_noacl, "noacl" },
187 { Opt_locallease, "locallease" },
188 { Opt_sign, "sign" },
Steve French4f5c10f2019-09-03 21:18:49 -0500189 { Opt_ignore_signature, "signloosely" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400190 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400191 { Opt_noac, "noac" },
192 { Opt_fsc, "fsc" },
193 { Opt_mfsymlinks, "mfsymlinks" },
194 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400195 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400196 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500197 { Opt_persistent, "persistenthandles"},
198 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600199 { Opt_resilient, "resilienthandles"},
200 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530201 { Opt_domainauto, "domainauto"},
Long Li8339dd32017-11-07 01:54:55 -0700202 { Opt_rdma, "rdma"},
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200203 { Opt_multichannel, "multichannel" },
204 { Opt_nomultichannel, "nomultichannel" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400205
206 { Opt_backupuid, "backupuid=%s" },
207 { Opt_backupgid, "backupgid=%s" },
208 { Opt_uid, "uid=%s" },
209 { Opt_cruid, "cruid=%s" },
210 { Opt_gid, "gid=%s" },
211 { Opt_file_mode, "file_mode=%s" },
212 { Opt_dirmode, "dirmode=%s" },
213 { Opt_dirmode, "dir_mode=%s" },
214 { Opt_port, "port=%s" },
Steve French563317e2019-09-08 23:22:02 -0500215 { Opt_min_enc_offload, "esize=%s" },
Steve Frenche8506d22019-02-28 21:32:15 -0600216 { Opt_blocksize, "bsize=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400217 { Opt_rsize, "rsize=%s" },
218 { Opt_wsize, "wsize=%s" },
219 { Opt_actimeo, "actimeo=%s" },
Steve Frenchca567eb2019-03-29 16:31:07 -0500220 { Opt_handletimeout, "handletimeout=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600221 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500222 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600223 { Opt_snapshot, "snapshot=%s" },
Aurelien Aptelbcc88802019-09-20 04:32:20 +0200224 { Opt_max_channels, "max_channels=%s" },
Steve French9fe5ff12019-06-24 20:39:04 -0500225 { Opt_compress, "compress=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400226
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100227 { Opt_blank_user, "user=" },
228 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400229 { Opt_user, "user=%s" },
230 { Opt_user, "username=%s" },
231 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100232 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400233 { Opt_pass, "pass=%s" },
234 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100235 { Opt_blank_ip, "ip=" },
236 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400237 { Opt_ip, "ip=%s" },
238 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400239 { Opt_ignore, "unc=%s" },
240 { Opt_ignore, "target=%s" },
241 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400242 { Opt_domain, "dom=%s" },
243 { Opt_domain, "domain=%s" },
244 { Opt_domain, "workgroup=%s" },
245 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400246 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400247 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400248 { Opt_netbiosname, "netbiosname=%s" },
249 { Opt_servern, "servern=%s" },
250 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400251 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400252 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400253 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400254
255 { Opt_ignore, "cred" },
256 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400257 { Opt_ignore, "cred=%s" },
258 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400259 { Opt_ignore, "guest" },
260 { Opt_ignore, "rw" },
261 { Opt_ignore, "ro" },
262 { Opt_ignore, "suid" },
263 { Opt_ignore, "nosuid" },
264 { Opt_ignore, "exec" },
265 { Opt_ignore, "noexec" },
266 { Opt_ignore, "nodev" },
267 { Opt_ignore, "noauto" },
268 { Opt_ignore, "dev" },
269 { Opt_ignore, "mand" },
270 { Opt_ignore, "nomand" },
Steve French9b9c5be2018-09-22 12:07:06 -0500271 { Opt_ignore, "relatime" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400272 { Opt_ignore, "_netdev" },
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -0300273 { Opt_rootfs, "rootfs" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400274
275 { Opt_err, NULL }
276};
277
278enum {
279 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
280 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400281 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
282 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400283 Opt_sec_none,
284
285 Opt_sec_err
286};
287
288static const match_table_t cifs_secflavor_tokens = {
289 { Opt_sec_krb5, "krb5" },
290 { Opt_sec_krb5i, "krb5i" },
291 { Opt_sec_krb5p, "krb5p" },
292 { Opt_sec_ntlmsspi, "ntlmsspi" },
293 { Opt_sec_ntlmssp, "ntlmssp" },
294 { Opt_ntlm, "ntlm" },
295 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400296 { Opt_sec_ntlmv2, "nontlm" },
297 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400298 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400299 { Opt_sec_lanman, "lanman" },
300 { Opt_sec_none, "none" },
301
302 { Opt_sec_err, NULL }
303};
304
Jeff Layton15b6a472012-05-16 07:50:15 -0400305/* cache flavors */
306enum {
307 Opt_cache_loose,
308 Opt_cache_strict,
309 Opt_cache_none,
Steve French83bbfa72019-08-27 23:58:54 -0500310 Opt_cache_ro,
Steve French41e033f2019-08-30 02:12:41 -0500311 Opt_cache_rw,
Jeff Layton15b6a472012-05-16 07:50:15 -0400312 Opt_cache_err
313};
314
315static const match_table_t cifs_cacheflavor_tokens = {
316 { Opt_cache_loose, "loose" },
317 { Opt_cache_strict, "strict" },
318 { Opt_cache_none, "none" },
Steve French83bbfa72019-08-27 23:58:54 -0500319 { Opt_cache_ro, "ro" },
Steve French41e033f2019-08-30 02:12:41 -0500320 { Opt_cache_rw, "singleclient" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400321 { Opt_cache_err, NULL }
322};
323
Jeff Layton23db65f2012-05-15 12:20:51 -0400324static const match_table_t cifs_smb_version_tokens = {
325 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600326 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000327 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500328 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500329 { Smb_302, SMB302_VERSION_STRING },
Kenneth D'souza4a3b38a2018-11-17 10:33:30 +0530330 { Smb_302, ALT_SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600331 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500332 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French9764c022017-09-17 10:41:35 -0500333 { Smb_3any, SMB3ANY_VERSION_STRING },
334 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600335 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400336};
337
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300338static int ip_connect(struct TCP_Server_Info *server);
339static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400340static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400341static void cifs_prune_tlinks(struct work_struct *work);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200342static char *extract_hostname(const char *unc);
343
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200344/*
345 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
346 * get their ip addresses changed at some point.
347 *
348 * This should be called with server->srv_mutex held.
349 */
350#ifdef CONFIG_CIFS_DFS_UPCALL
351static int reconn_set_ipaddr(struct TCP_Server_Info *server)
352{
353 int rc;
354 int len;
355 char *unc, *ipaddr = NULL;
356
357 if (!server->hostname)
358 return -EINVAL;
359
360 len = strlen(server->hostname) + 3;
361
362 unc = kmalloc(len, GFP_KERNEL);
363 if (!unc) {
364 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
365 return -ENOMEM;
366 }
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +1000367 scnprintf(unc, len, "\\\\%s", server->hostname);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200368
369 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
370 kfree(unc);
371
372 if (rc < 0) {
373 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
374 __func__, server->hostname, rc);
375 return rc;
376 }
377
378 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
379 strlen(ipaddr));
380 kfree(ipaddr);
381
382 return !rc ? -1 : 0;
383}
384#else
385static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
386{
387 return 0;
388}
389#endif
390
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200391#ifdef CONFIG_CIFS_DFS_UPCALL
392struct super_cb_data {
393 struct TCP_Server_Info *server;
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300394 struct super_block *sb;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200395};
396
397/* These functions must be called with server->srv_mutex held */
398
399static void super_cb(struct super_block *sb, void *arg)
400{
401 struct super_cb_data *d = arg;
402 struct cifs_sb_info *cifs_sb;
403 struct cifs_tcon *tcon;
404
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300405 if (d->sb)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200406 return;
407
408 cifs_sb = CIFS_SB(sb);
409 tcon = cifs_sb_master_tcon(cifs_sb);
410 if (tcon->ses->server == d->server)
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300411 d->sb = sb;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200412}
413
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300414static struct super_block *get_tcp_super(struct TCP_Server_Info *server)
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200415{
416 struct super_cb_data d = {
417 .server = server,
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300418 .sb = NULL,
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200419 };
420
421 iterate_supers_type(&cifs_fs_type, super_cb, &d);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300422
423 if (unlikely(!d.sb))
424 return ERR_PTR(-ENOENT);
425 /*
426 * Grab an active reference in order to prevent automounts (DFS links)
427 * of expiring and then freeing up our cifs superblock pointer while
428 * we're doing failover.
429 */
430 cifs_sb_active(d.sb);
431 return d.sb;
432}
433
434static inline void put_tcp_super(struct super_block *sb)
435{
436 if (!IS_ERR_OR_NULL(sb))
437 cifs_sb_deactive(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200438}
439
440static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
441 struct cifs_sb_info *cifs_sb,
442 struct dfs_cache_tgt_list *tgt_list,
443 struct dfs_cache_tgt_iterator **tgt_it)
444{
445 const char *name;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200446
447 if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list ||
448 !server->nr_targets)
449 return;
450
451 if (!*tgt_it) {
452 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
453 } else {
454 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
455 if (!*tgt_it)
456 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
457 }
458
459 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
460
461 name = dfs_cache_get_tgt_name(*tgt_it);
462
463 kfree(server->hostname);
464
465 server->hostname = extract_hostname(name);
Dan Carpenter84288172019-01-05 15:25:29 +0300466 if (IS_ERR(server->hostname)) {
467 cifs_dbg(FYI,
468 "%s: failed to extract hostname from target: %ld\n",
469 __func__, PTR_ERR(server->hostname));
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200470 }
471}
472
473static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
474 struct dfs_cache_tgt_list *tl,
475 struct dfs_cache_tgt_iterator **it)
476{
477 if (!cifs_sb->origin_fullpath)
478 return -EOPNOTSUPP;
479 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
480}
481#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Jeff Laytond5c56052008-12-01 18:42:33 -0500483/*
484 * cifs tcp session reconnection
485 *
486 * mark tcp session as reconnecting so temporarily locked
487 * mark all smb sessions as reconnecting for tcp session
488 * reconnect tcp session
489 * wake up waiters on reconnection? - (not needed currently)
490 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400491int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492cifs_reconnect(struct TCP_Server_Info *server)
493{
494 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500495 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000496 struct cifs_ses *ses;
497 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000498 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400499 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200500#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300501 struct super_block *sb = NULL;
Paulo Alcantara23324402018-11-20 14:37:18 -0200502 struct cifs_sb_info *cifs_sb = NULL;
503 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200504 struct dfs_cache_tgt_iterator *tgt_it = NULL;
505#endif
Steve French50c2f752007-07-13 00:33:32 +0000506
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200508 server->nr_targets = 1;
509#ifdef CONFIG_CIFS_DFS_UPCALL
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000510 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300511 sb = get_tcp_super(server);
512 if (IS_ERR(sb)) {
513 rc = PTR_ERR(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200514 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
515 __func__, rc);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300516 sb = NULL;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200517 } else {
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300518 cifs_sb = CIFS_SB(sb);
519
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200520 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
Steve French55a7f002019-01-01 17:19:45 -0600521 if (rc && (rc != -EOPNOTSUPP)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000522 cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200523 __func__);
524 } else {
525 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
526 }
527 }
528 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
529 server->nr_targets);
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000530 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200531#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000532 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000533 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 next time through the loop */
535 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300536#ifdef CONFIG_CIFS_DFS_UPCALL
537 dfs_cache_free_tgts(&tgt_list);
538 put_tcp_super(sb);
539#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return rc;
541 } else
542 server->tcpStatus = CifsNeedReconnect;
543 spin_unlock(&GlobalMid_Lock);
544 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400545 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
Steve French6e4d3bb2018-09-22 11:25:04 -0500547 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500548 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
550 /* before reconnecting the tcp session, mark the smb session (uid)
551 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500552 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
553 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530554 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500555 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000556 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500557 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500558 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000559 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500560 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100562 if (ses->tcon_ipc)
563 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530565 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500566
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500568 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500569 mutex_lock(&server->srv_mutex);
Long Li1d2a4f52019-05-13 21:01:28 -0700570 if (server->ssocket) {
571 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
572 server->ssocket->state, server->ssocket->flags);
573 kernel_sock_shutdown(server->ssocket, SHUT_WR);
574 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
575 server->ssocket->state, server->ssocket->flags);
576 sock_release(server->ssocket);
577 server->ssocket = NULL;
578 }
579 server->sequence_number = 0;
580 server->session_estab = false;
581 kfree(server->session_key.response);
582 server->session_key.response = NULL;
583 server->session_key.len = 0;
584 server->lstrp = jiffies;
Long Li214bab42019-04-05 21:36:35 +0000585
586 /* mark submitted MIDs for retry and issue callback */
587 INIT_LIST_HEAD(&retry_list);
588 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
589 spin_lock(&GlobalMid_Lock);
590 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
591 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700592 kref_get(&mid_entry->refcount);
Long Li214bab42019-04-05 21:36:35 +0000593 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
594 mid_entry->mid_state = MID_RETRY_NEEDED;
595 list_move(&mid_entry->qhead, &retry_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700596 mid_entry->mid_flags |= MID_DELETED;
Long Li214bab42019-04-05 21:36:35 +0000597 }
598 spin_unlock(&GlobalMid_Lock);
Long Li1d2a4f52019-05-13 21:01:28 -0700599 mutex_unlock(&server->srv_mutex);
Long Li214bab42019-04-05 21:36:35 +0000600
601 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
602 list_for_each_safe(tmp, tmp2, &retry_list) {
603 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
604 list_del_init(&mid_entry->qhead);
605 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700606 cifs_mid_q_entry_release(mid_entry);
Long Li214bab42019-04-05 21:36:35 +0000607 }
608
Long Li1d2a4f52019-05-13 21:01:28 -0700609 if (cifs_rdma_enabled(server)) {
610 mutex_lock(&server->srv_mutex);
Long Li050b8c32019-04-04 11:35:42 -0500611 smbd_destroy(server);
Long Li1d2a4f52019-05-13 21:01:28 -0700612 mutex_unlock(&server->srv_mutex);
613 }
Jeff Layton3c1105d2011-05-22 07:09:13 -0400614
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400615 do {
Steve French6c3d8902006-07-31 22:46:20 +0000616 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300617
Jeff Layton73e216a2013-09-05 08:38:10 -0400618 mutex_lock(&server->srv_mutex);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200619 /*
620 * Set up next DFS target server (if any) for reconnect. If DFS
621 * feature is disabled, then we will retry last server we
622 * connected to before.
623 */
Long Li781a8052017-11-22 17:38:36 -0700624 if (cifs_rdma_enabled(server))
625 rc = smbd_reconnect(server);
626 else
627 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000628 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500629 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200630#ifdef CONFIG_CIFS_DFS_UPCALL
631 reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
632 &tgt_it);
633#endif
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200634 rc = reconn_set_ipaddr(server);
635 if (rc) {
636 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
637 __func__, rc);
638 }
Federico Sauter4afe2602015-03-17 17:45:28 +0100639 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700640 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 } else {
642 atomic_inc(&tcpSesReconnectCount);
Pavel Shilovsky335b7b62019-01-16 11:12:41 -0800643 set_credits(server, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000645 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000646 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000647 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100648 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400650 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500651
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200652#ifdef CONFIG_CIFS_DFS_UPCALL
653 if (tgt_it) {
654 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
655 tgt_it);
656 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000657 cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200658 __func__, rc);
659 }
660 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
661 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000662 cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200663 __func__, rc);
664 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200665 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300666
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200667 }
Paulo Alcantara (SUSE)8354d882019-11-22 12:30:51 -0300668
669 put_tcp_super(sb);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200670#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400671 if (server->tcpStatus == CifsNeedNegotiate)
672 mod_delayed_work(cifsiod_wq, &server->echo, 0);
673
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 return rc;
675}
676
Jeff Laytonc74093b2011-01-11 07:24:23 -0500677static void
678cifs_echo_request(struct work_struct *work)
679{
680 int rc;
681 struct TCP_Server_Info *server = container_of(work,
682 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400683 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500684
Jeff Layton247ec9b2011-02-04 17:09:50 -0500685 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400686 * If we need to renegotiate, set echo interval to zero to
687 * immediately call echo service where we can renegotiate.
688 */
689 if (server->tcpStatus == CifsNeedNegotiate)
690 echo_interval = 0;
691 else
692 echo_interval = server->echo_interval;
693
694 /*
695 * We cannot send an echo if it is disabled.
696 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500697 */
Steve French4fcd1812016-06-22 20:12:05 -0500698
699 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400700 server->tcpStatus == CifsExiting ||
701 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400702 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600703 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500704 goto requeue_echo;
705
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400706 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500707 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500708 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
709 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500710
711requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400712 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500713}
714
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400715static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400716allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400717{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400718 if (!server->bigbuf) {
719 server->bigbuf = (char *)cifs_buf_get();
720 if (!server->bigbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000721 cifs_server_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400722 msleep(3000);
723 /* retry will check if exiting */
724 return false;
725 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400726 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400727 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400728 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400729 }
730
Jeff Layton2a37ef92011-10-19 15:29:23 -0400731 if (!server->smallbuf) {
732 server->smallbuf = (char *)cifs_small_buf_get();
733 if (!server->smallbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000734 cifs_server_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400735 msleep(1000);
736 /* retry will check if exiting */
737 return false;
738 }
739 /* beginning of smb buffer is cleared in our buf_get */
740 } else {
741 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400742 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400743 }
744
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400745 return true;
746}
747
Jeff Laytonba749e62011-10-11 06:41:32 -0400748static bool
749server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400750{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300751 /*
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000752 * We need to wait 3 echo intervals to make sure we handle such
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300753 * situations right:
754 * 1s client sends a normal SMB request
Ronnie Sahlbergbecc2ba2019-07-24 11:43:49 +1000755 * 2s client gets a response
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300756 * 30s echo workqueue job pops, and decides we got a response recently
757 * and don't need to send another
758 * ...
759 * 65s kernel_recvmsg times out, and we see that we haven't gotten
760 * a response in >60s.
761 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200762 if ((server->tcpStatus == CifsGood ||
763 server->tcpStatus == CifsNeedNegotiate) &&
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000764 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000765 cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
766 (3 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400767 cifs_reconnect(server);
768 wake_up(&server->response_q);
769 return true;
770 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400771
Jeff Laytonba749e62011-10-11 06:41:32 -0400772 return false;
773}
774
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800775static inline bool
776zero_credits(struct TCP_Server_Info *server)
777{
778 int val;
779
780 spin_lock(&server->req_lock);
781 val = server->credits + server->echo_credits + server->oplock_credits;
782 if (server->in_flight == 0 && val == 0) {
783 spin_unlock(&server->req_lock);
784 return true;
785 }
786 spin_unlock(&server->req_lock);
787 return false;
788}
789
Al Viro71335662016-01-09 19:54:50 -0500790static int
791cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400792{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400793 int length = 0;
794 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400795
Al Viro71335662016-01-09 19:54:50 -0500796 smb_msg->msg_control = NULL;
797 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400798
Al Viro71335662016-01-09 19:54:50 -0500799 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500800 try_to_freeze();
801
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800802 /* reconnect if no credits and no requests in flight */
803 if (zero_credits(server)) {
804 cifs_reconnect(server);
805 return -ECONNABORTED;
806 }
807
Al Viro71335662016-01-09 19:54:50 -0500808 if (server_unresponsive(server))
809 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700810 if (cifs_rdma_enabled(server) && server->smbd_conn)
811 length = smbd_recv(server->smbd_conn, smb_msg);
812 else
813 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500814
815 if (server->tcpStatus == CifsExiting)
816 return -ESHUTDOWN;
817
818 if (server->tcpStatus == CifsNeedReconnect) {
819 cifs_reconnect(server);
820 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400821 }
822
Al Viro71335662016-01-09 19:54:50 -0500823 if (length == -ERESTARTSYS ||
824 length == -EAGAIN ||
825 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400826 /*
827 * Minimum sleep to prevent looping, allowing socket
828 * to clear and app threads to set tcpStatus
829 * CifsNeedReconnect if server hung.
830 */
831 usleep_range(1000, 2000);
832 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400833 continue;
Al Viro71335662016-01-09 19:54:50 -0500834 }
835
836 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500837 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400838 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500839 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400840 }
841 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400842 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400843}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400844
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400845int
846cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
847 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400848{
Al Viro71335662016-01-09 19:54:50 -0500849 struct msghdr smb_msg;
850 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100851 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400852
Al Viro71335662016-01-09 19:54:50 -0500853 return cifs_readv_from_socket(server, &smb_msg);
854}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400855
Al Viro71335662016-01-09 19:54:50 -0500856int
857cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700858 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500859{
860 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700861 struct bio_vec bv = {
862 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100863 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500864 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400865}
866
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400867static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400868is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400869{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400870 /*
871 * The first byte big endian of the length field,
872 * is actually not part of the length but the type
873 * with the most common, zero, as regular data.
874 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400875 switch (type) {
876 case RFC1002_SESSION_MESSAGE:
877 /* Regular SMB response */
878 return true;
879 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500880 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400881 break;
882 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500883 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400884 break;
885 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400886 /*
887 * We get this from Windows 98 instead of an error on
888 * SMB negprot response.
889 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500890 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400891 /* give server a second to clean up */
892 msleep(1000);
893 /*
894 * Always try 445 first on reconnect since we get NACK
895 * on some if we ever connected to port 139 (the NACK
896 * is since we do not begin with RFC1001 session
897 * initialize frame).
898 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400899 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400900 cifs_reconnect(server);
901 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400902 break;
903 default:
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000904 cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400905 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400906 }
907
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400908 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400909}
910
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400911void
912dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400913{
914#ifdef CONFIG_CIFS_STATS2
915 mid->when_received = jiffies;
916#endif
917 spin_lock(&GlobalMid_Lock);
918 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400919 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400920 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400921 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000922 /*
923 * Trying to handle/dequeue a mid after the send_recv()
924 * function has finished processing it is a bug.
925 */
926 if (mid->mid_flags & MID_DELETED)
927 printk_once(KERN_WARNING
928 "trying to dequeue a deleted mid\n");
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700929 else {
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000930 list_del_init(&mid->qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700931 mid->mid_flags |= MID_DELETED;
932 }
Jeff Laytonea1f4502011-10-19 15:29:05 -0400933 spin_unlock(&GlobalMid_Lock);
934}
935
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800936static unsigned int
937smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
938{
939 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
940
941 /*
942 * SMB1 does not use credits.
943 */
944 if (server->vals->header_preamble_size)
945 return 0;
946
947 return le16_to_cpu(shdr->CreditRequest);
948}
949
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400950static void
951handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400952 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400953{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400954 if (server->ops->check_trans2 &&
955 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400956 return;
Pavel Shilovsky86a79642019-11-21 11:35:13 -0800957 mid->credits_received = smb2_get_credits_from_hdr(buf, server);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400958 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400959 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400960 /* Was previous buf put in mpx struct for multi-rsp? */
961 if (!mid->multiRsp) {
962 /* smb buffer will be freed by user thread */
963 if (server->large_buf)
964 server->bigbuf = NULL;
965 else
966 server->smallbuf = NULL;
967 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400968 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400969}
970
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400971static void clean_demultiplex_info(struct TCP_Server_Info *server)
972{
973 int length;
974
975 /* take it off the list, if it's not already */
976 spin_lock(&cifs_tcp_ses_lock);
977 list_del_init(&server->tcp_ses_list);
978 spin_unlock(&cifs_tcp_ses_lock);
979
980 spin_lock(&GlobalMid_Lock);
981 server->tcpStatus = CifsExiting;
982 spin_unlock(&GlobalMid_Lock);
983 wake_up_all(&server->response_q);
984
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400985 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300986 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400987 if (server->credits <= 0)
988 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300989 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400990 /*
991 * Although there should not be any requests blocked on this queue it
992 * can not hurt to be paranoid and try to wake up requests that may
993 * haven been blocked when more than 50 at time were on the wire to the
994 * same server - they now will see the session is in exit state and get
995 * out of SendReceive.
996 */
997 wake_up_all(&server->request_q);
998 /* give those requests time to exit */
999 msleep(125);
Long Li050b8c32019-04-04 11:35:42 -05001000 if (cifs_rdma_enabled(server))
1001 smbd_destroy(server);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001002 if (server->ssocket) {
1003 sock_release(server->ssocket);
1004 server->ssocket = NULL;
1005 }
1006
1007 if (!list_empty(&server->pending_mid_q)) {
1008 struct list_head dispose_list;
1009 struct mid_q_entry *mid_entry;
1010 struct list_head *tmp, *tmp2;
1011
1012 INIT_LIST_HEAD(&dispose_list);
1013 spin_lock(&GlobalMid_Lock);
1014 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
1015 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -05001016 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovskyabe57072019-10-22 08:41:42 -07001017 kref_get(&mid_entry->refcount);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -04001018 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001019 list_move(&mid_entry->qhead, &dispose_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -07001020 mid_entry->mid_flags |= MID_DELETED;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001021 }
1022 spin_unlock(&GlobalMid_Lock);
1023
1024 /* now walk dispose list and issue callbacks */
1025 list_for_each_safe(tmp, tmp2, &dispose_list) {
1026 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -05001027 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001028 list_del_init(&mid_entry->qhead);
1029 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -07001030 cifs_mid_q_entry_release(mid_entry);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001031 }
1032 /* 1/8th of sec is more than enough time for them to exit */
1033 msleep(125);
1034 }
1035
1036 if (!list_empty(&server->pending_mid_q)) {
1037 /*
1038 * mpx threads have not exited yet give them at least the smb
1039 * send timeout time for long ops.
1040 *
1041 * Due to delays on oplock break requests, we need to wait at
1042 * least 45 seconds before giving up on a request getting a
1043 * response and going ahead and killing cifsd.
1044 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001045 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001046 msleep(46000);
1047 /*
1048 * If threads still have not exited they are probably never
1049 * coming home not much else we can do but free the memory.
1050 */
1051 }
1052
1053 kfree(server->hostname);
1054 kfree(server);
1055
1056 length = atomic_dec_return(&tcpSesAllocCount);
1057 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -07001058 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001059}
1060
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001061static int
Jeff Laytone9097ab2011-10-19 15:29:40 -04001062standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1063{
1064 int length;
1065 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +10001066 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001067
1068 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001069 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
1070 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001071 cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001072 cifs_reconnect(server);
1073 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +04001074 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001075 }
1076
1077 /* switch to large buffer if too big for a small one */
1078 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
1079 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001080 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001081 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001082 }
1083
1084 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001085 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001086 pdu_length - HEADER_SIZE(server) + 1
1087 + server->vals->header_preamble_size);
1088
Jeff Laytone9097ab2011-10-19 15:29:40 -04001089 if (length < 0)
1090 return length;
1091 server->total_read += length;
1092
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001093 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001094
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08001095 return cifs_handle_standard(server, mid);
1096}
1097
1098int
1099cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1100{
1101 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1102 int length;
1103
Jeff Laytone9097ab2011-10-19 15:29:40 -04001104 /*
1105 * We know that we received enough to get to the MID as we
1106 * checked the pdu_length earlier. Now check to see
1107 * if the rest of the header is OK. We borrow the length
1108 * var for the rest of the loop to avoid a new stack var.
1109 *
1110 * 48 bytes is enough to display the header and a little bit
1111 * into the payload for debugging purposes.
1112 */
Steve French373512e2015-12-18 13:05:30 -06001113 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001114 if (length != 0)
1115 cifs_dump_mem("Bad SMB: ", buf,
1116 min_t(unsigned int, server->total_read, 48));
1117
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001118 if (server->ops->is_session_expired &&
1119 server->ops->is_session_expired(buf)) {
1120 cifs_reconnect(server);
1121 wake_up(&server->response_q);
1122 return -1;
1123 }
1124
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001125 if (server->ops->is_status_pending &&
Pavel Shilovsky66265f12019-01-23 17:11:16 -08001126 server->ops->is_status_pending(buf, server))
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001127 return -1;
1128
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001129 if (!mid)
1130 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001131
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001132 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001133 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001134}
1135
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001136static void
1137smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
1138{
1139 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
1140
1141 /*
1142 * SMB1 does not use credits.
1143 */
1144 if (server->vals->header_preamble_size)
1145 return;
1146
1147 if (shdr->CreditRequest) {
1148 spin_lock(&server->req_lock);
1149 server->credits += le16_to_cpu(shdr->CreditRequest);
1150 spin_unlock(&server->req_lock);
1151 wake_up(&server->request_q);
1152 }
1153}
1154
1155
Jeff Laytone9097ab2011-10-19 15:29:40 -04001156static int
Al Viro7c97c202011-06-21 08:51:28 -04001157cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001159 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001160 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001161 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001162 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001163 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001164 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001165 struct mid_q_entry *mids[MAX_COMPOUND];
1166 char *bufs[MAX_COMPOUND];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -05001169 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001170
1171 length = atomic_inc_return(&tcpSesAllocCount);
1172 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001173 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001175 set_freezable();
Eric W. Biederman33da8e72019-08-16 12:33:54 -05001176 allow_kernel_signal(SIGKILL);
Jeff Layton469ee612008-10-16 18:46:39 +00001177 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001178 if (try_to_freeze())
1179 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001180
Jeff Layton2a37ef92011-10-19 15:29:23 -04001181 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001182 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001183
Jeff Layton2a37ef92011-10-19 15:29:23 -04001184 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001185 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001186 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001187
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001188 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001189 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001190 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001191
1192 if (server->vals->header_preamble_size == 0)
1193 server->total_read = 0;
1194 else
1195 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001196
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001197 /*
1198 * The right amount was read from socket - 4 bytes,
1199 * so we can now interpret the length field.
1200 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001201 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001202
Joe Perchesf96637b2013-05-04 22:12:25 -05001203 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001204 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001205 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001206next_pdu:
1207 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001208
Jeff Layton89482a52011-10-19 15:28:57 -04001209 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001210 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001211 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001212 cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001213 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001214 cifs_reconnect(server);
1215 wake_up(&server->response_q);
1216 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001217 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001218
Jeff Layton89482a52011-10-19 15:28:57 -04001219 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001220 length = cifs_read_from_socket(server,
1221 buf + server->vals->header_preamble_size,
1222 HEADER_SIZE(server) - 1
1223 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001224 if (length < 0)
1225 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001226 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001227
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001228 if (server->ops->next_header) {
1229 next_offset = server->ops->next_header(buf);
1230 if (next_offset)
1231 server->pdu_size = next_offset;
1232 }
1233
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001234 memset(mids, 0, sizeof(mids));
1235 memset(bufs, 0, sizeof(bufs));
1236 num_mids = 0;
1237
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001238 if (server->ops->is_transform_hdr &&
1239 server->ops->receive_transform &&
1240 server->ops->is_transform_hdr(buf)) {
1241 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001242 mids,
1243 bufs,
1244 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001245 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001246 mids[0] = server->ops->find_mid(server, buf);
1247 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001248 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001249
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001250 if (!mids[0] || !mids[0]->receive)
1251 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001252 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001253 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001254 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001255
Lars Persson696e4202018-06-25 14:05:25 +02001256 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001257 for (i = 0; i < num_mids; i++)
1258 if (mids[i])
1259 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001260 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001261 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001262
Steve Frenchfda35942011-01-20 18:06:34 +00001263 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001264
1265 for (i = 0; i < num_mids; i++) {
1266 if (mids[i] != NULL) {
1267 mids[i]->resp_buf_size = server->pdu_size;
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001268
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001269 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1270 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001271
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001272 cifs_mid_q_entry_release(mids[i]);
1273 } else if (server->ops->is_oplock_break &&
1274 server->ops->is_oplock_break(bufs[i],
1275 server)) {
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001276 smb2_add_credits_from_hdr(bufs[i], server);
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001277 cifs_dbg(FYI, "Received oplock break\n");
1278 } else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001279 cifs_server_dbg(VFS, "No task to wake, unknown frame "
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001280 "received! NumMids %d\n",
1281 atomic_read(&midCount));
1282 cifs_dump_mem("Received Data is: ", bufs[i],
1283 HEADER_SIZE(server));
Ronnie Sahlberg3e272572019-07-06 06:43:08 +10001284 smb2_add_credits_from_hdr(bufs[i], server);
Steve French39798772006-05-31 22:40:51 +00001285#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001286 if (server->ops->dump_detail)
1287 server->ops->dump_detail(bufs[i],
1288 server);
1289 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001290#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001291 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001292 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001293
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001294 if (pdu_length > server->pdu_size) {
1295 if (!allocate_buffers(server))
1296 continue;
1297 pdu_length -= server->pdu_size;
1298 server->total_read = 0;
1299 server->large_buf = false;
1300 buf = server->smallbuf;
1301 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001302 }
1303 } /* end while !EXITING */
1304
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001305 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001306 cifs_buf_release(server->bigbuf);
1307 if (server->smallbuf) /* no sense logging a debug message if NULL */
1308 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001310 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001311 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001312
1313 /* if server->tsk was NULL then wait for a signal before exiting */
1314 if (!task_to_wake) {
1315 set_current_state(TASK_INTERRUPTIBLE);
1316 while (!signal_pending(current)) {
1317 schedule();
1318 set_current_state(TASK_INTERRUPTIBLE);
1319 }
1320 set_current_state(TASK_RUNNING);
1321 }
1322
Jeff Layton0468a2c2008-12-01 07:09:35 -05001323 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324}
1325
Jeff Laytonc359cf32007-11-16 22:22:06 +00001326/* extract the host portion of the UNC string */
1327static char *
1328extract_hostname(const char *unc)
1329{
1330 const char *src;
1331 char *dst, *delim;
1332 unsigned int len;
1333
1334 /* skip double chars at beginning of string */
1335 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001336 if (strlen(unc) < 3)
1337 return ERR_PTR(-EINVAL);
1338 for (src = unc; *src && *src == '\\'; src++)
1339 ;
1340 if (!*src)
1341 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001342
1343 /* delimiter between hostname and sharename is always '\\' now */
1344 delim = strchr(src, '\\');
1345 if (!delim)
1346 return ERR_PTR(-EINVAL);
1347
1348 len = delim - src;
1349 dst = kmalloc((len + 1), GFP_KERNEL);
1350 if (dst == NULL)
1351 return ERR_PTR(-ENOMEM);
1352
1353 memcpy(dst, src, len);
1354 dst[len] = '\0';
1355
1356 return dst;
1357}
1358
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001359static int get_option_ul(substring_t args[], unsigned long *option)
1360{
1361 int rc;
1362 char *string;
1363
1364 string = match_strdup(args);
1365 if (string == NULL)
1366 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001367 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001368 kfree(string);
1369
1370 return rc;
1371}
1372
Eric W. Biederman3da46562013-02-06 01:37:39 -08001373static int get_option_uid(substring_t args[], kuid_t *result)
1374{
1375 unsigned long value;
1376 kuid_t uid;
1377 int rc;
1378
1379 rc = get_option_ul(args, &value);
1380 if (rc)
1381 return rc;
1382
1383 uid = make_kuid(current_user_ns(), value);
1384 if (!uid_valid(uid))
1385 return -EINVAL;
1386
1387 *result = uid;
1388 return 0;
1389}
1390
1391static int get_option_gid(substring_t args[], kgid_t *result)
1392{
1393 unsigned long value;
1394 kgid_t gid;
1395 int rc;
1396
1397 rc = get_option_ul(args, &value);
1398 if (rc)
1399 return rc;
1400
1401 gid = make_kgid(current_user_ns(), value);
1402 if (!gid_valid(gid))
1403 return -EINVAL;
1404
1405 *result = gid;
1406 return 0;
1407}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001408
1409static int cifs_parse_security_flavors(char *value,
1410 struct smb_vol *vol)
1411{
1412
1413 substring_t args[MAX_OPT_ARGS];
1414
Jeff Layton1e3cc572013-06-10 17:12:23 -05001415 /*
1416 * With mount options, the last one should win. Reset any existing
1417 * settings back to default.
1418 */
1419 vol->sectype = Unspecified;
1420 vol->sign = false;
1421
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001422 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001423 case Opt_sec_krb5p:
1424 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1425 return 1;
1426 case Opt_sec_krb5i:
1427 vol->sign = true;
1428 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001429 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001430 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001431 break;
1432 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001433 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001434 /* Fallthrough */
1435 case Opt_sec_ntlmssp:
1436 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001437 break;
1438 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001439 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001440 /* Fallthrough */
1441 case Opt_ntlm:
1442 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001443 break;
1444 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001445 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001446 /* Fallthrough */
1447 case Opt_sec_ntlmv2:
1448 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001449 break;
1450#ifdef CONFIG_CIFS_WEAK_PW_HASH
1451 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001452 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001453 break;
1454#endif
1455 case Opt_sec_none:
1456 vol->nullauth = 1;
1457 break;
1458 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001459 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 return 1;
1461 }
1462
1463 return 0;
1464}
1465
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001467cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1468{
1469 substring_t args[MAX_OPT_ARGS];
1470
1471 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1472 case Opt_cache_loose:
1473 vol->direct_io = false;
1474 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001475 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001476 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001477 break;
1478 case Opt_cache_strict:
1479 vol->direct_io = false;
1480 vol->strict_io = true;
Steve French83bbfa72019-08-27 23:58:54 -05001481 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001482 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001483 break;
1484 case Opt_cache_none:
1485 vol->direct_io = true;
1486 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001487 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001488 vol->cache_rw = false;
Steve French83bbfa72019-08-27 23:58:54 -05001489 break;
1490 case Opt_cache_ro:
1491 vol->direct_io = false;
1492 vol->strict_io = false;
1493 vol->cache_ro = true;
Steve French41e033f2019-08-30 02:12:41 -05001494 vol->cache_rw = false;
1495 break;
1496 case Opt_cache_rw:
1497 vol->direct_io = false;
1498 vol->strict_io = false;
1499 vol->cache_ro = false;
1500 vol->cache_rw = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001501 break;
1502 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001503 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001504 return 1;
1505 }
1506 return 0;
1507}
1508
1509static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001510cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001511{
1512 substring_t args[MAX_OPT_ARGS];
1513
1514 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001515#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001516 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001517 if (disable_legacy_dialects) {
1518 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1519 return 1;
1520 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001521 if (is_smb3) {
1522 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1523 return 1;
1524 }
Jeff Layton23db65f2012-05-15 12:20:51 -04001525 vol->ops = &smb1_operations;
1526 vol->vals = &smb1_values;
1527 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001528 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001529 if (disable_legacy_dialects) {
1530 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1531 return 1;
1532 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001533 if (is_smb3) {
1534 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1535 return 1;
1536 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001537 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001538 vol->vals = &smb20_values;
1539 break;
Steve French74204512018-06-19 14:34:08 -05001540#else
1541 case Smb_1:
1542 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1543 return 1;
1544 case Smb_20:
1545 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1546 return 1;
1547#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001548 case Smb_21:
1549 vol->ops = &smb21_operations;
1550 vol->vals = &smb21_values;
1551 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001552 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001553 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001554 vol->vals = &smb30_values;
1555 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001556 case Smb_302:
1557 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1558 vol->vals = &smb302_values;
1559 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001560 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001561 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001562 vol->vals = &smb311_values;
1563 break;
Steve French9764c022017-09-17 10:41:35 -05001564 case Smb_3any:
1565 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1566 vol->vals = &smb3any_values;
1567 break;
1568 case Smb_default:
1569 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1570 vol->vals = &smbdefault_values;
1571 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001572 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001573 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001574 return 1;
1575 }
1576 return 0;
1577}
1578
Jeff Laytond387a5c2012-12-10 06:10:46 -05001579/*
1580 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1581 * fields with the result. Returns 0 on success and an error otherwise.
1582 */
1583static int
1584cifs_parse_devname(const char *devname, struct smb_vol *vol)
1585{
1586 char *pos;
1587 const char *delims = "/\\";
1588 size_t len;
1589
Yao Liu68e26722019-01-28 19:47:28 +08001590 if (unlikely(!devname || !*devname)) {
1591 cifs_dbg(VFS, "Device name not specified.\n");
1592 return -EINVAL;
1593 }
1594
Jeff Laytond387a5c2012-12-10 06:10:46 -05001595 /* make sure we have a valid UNC double delimiter prefix */
1596 len = strspn(devname, delims);
1597 if (len != 2)
1598 return -EINVAL;
1599
1600 /* find delimiter between host and sharename */
1601 pos = strpbrk(devname + 2, delims);
1602 if (!pos)
1603 return -EINVAL;
1604
1605 /* skip past delimiter */
1606 ++pos;
1607
1608 /* now go until next delimiter or end of string */
1609 len = strcspn(pos, delims);
1610
1611 /* move "pos" up to delimiter or NULL */
1612 pos += len;
1613 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1614 if (!vol->UNC)
1615 return -ENOMEM;
1616
1617 convert_delimiter(vol->UNC, '\\');
1618
Sachin Prabhu11e31642016-02-08 13:44:01 +05301619 /* skip any delimiter */
1620 if (*pos == '/' || *pos == '\\')
1621 pos++;
1622
1623 /* If pos is NULL then no prepath */
1624 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001625 return 0;
1626
1627 vol->prepath = kstrdup(pos, GFP_KERNEL);
1628 if (!vol->prepath)
1629 return -ENOMEM;
1630
1631 return 0;
1632}
1633
Jeff Layton23db65f2012-05-15 12:20:51 -04001634static int
Sean Finneyb9468452011-04-11 13:19:32 +00001635cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001636 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001638 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001639 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 unsigned int temp_len, i, j;
1641 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001642 short int override_uid = -1;
1643 short int override_gid = -1;
1644 bool uid_specified = false;
1645 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001646 bool sloppy = false;
1647 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001648 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001649 char *string = NULL;
1650 char *tmp_end, *value;
1651 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001652 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001653 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001654 unsigned short port = 0;
1655 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656
1657 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001658 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001659 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660
Jeff Layton6ee95422012-11-26 11:09:57 -05001661 /* ensure we always start with zeroed-out smb_vol */
1662 memset(vol, 0, sizeof(*vol));
1663
Jeff Layton88463992010-11-22 15:31:03 -05001664 /*
1665 * does not have to be perfect mapping since field is
1666 * informational, only used for servers that do not support
1667 * port 445 and it can be overridden at mount time
1668 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001669 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1670 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001671 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1672
Jeff Layton1397f2e2011-01-07 11:30:28 -05001673 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001674 /* null target name indicates to use *SMBSERVR default called name
1675 if we end up sending RFC1001 session initialize */
1676 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001677 vol->cred_uid = current_uid();
1678 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001679 vol->linux_gid = current_gid();
Steve Frenche8506d22019-02-28 21:32:15 -06001680 vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
Steve French2baa2682014-09-27 02:19:01 -05001681 /*
1682 * default to SFM style remapping of seven reserved characters
1683 * unless user overrides it or we negotiate CIFS POSIX where
1684 * it is unnecessary. Can not simultaneously use more than one mapping
1685 * since then readdir could list files that open could not open
1686 */
1687 vol->remap = true;
1688
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001689 /* default to only allowing write access to owner of the mount */
1690 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
1692 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001693 /* default is always to request posix paths. */
1694 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001695 /* default to using server inode numbers where available */
1696 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001697
Jeff Layton1b359202012-09-19 15:20:27 -07001698 /* default is to use strict cifs caching semantics */
1699 vol->strict_io = true;
1700
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301701 vol->actimeo = CIFS_DEF_ACTIMEO;
1702
Steve Frenchca567eb2019-03-29 16:31:07 -05001703 /* Most clients set timeout to 0, allows server to use its default */
1704 vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1705
Steve French9764c022017-09-17 10:41:35 -05001706 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1707 vol->ops = &smb30_operations;
1708 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001709
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001710 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1711
Aurelien Aptelbcc88802019-09-20 04:32:20 +02001712 /* default to no multichannel (single server connection) */
1713 vol->multichannel = false;
1714 vol->max_channels = 1;
1715
Sean Finneyb9468452011-04-11 13:19:32 +00001716 if (!mountdata)
1717 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
Sean Finneyb9468452011-04-11 13:19:32 +00001719 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1720 if (!mountdata_copy)
1721 goto cifs_parse_mount_err;
1722
1723 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001724 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001725
Steve French50c2f752007-07-13 00:33:32 +00001726 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001727 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 separator[0] = options[4];
1729 options += 5;
1730 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001731 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 }
1733 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001734 vol->backupuid_specified = false; /* no backup intent for a user */
1735 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001736
Jeff Layton37d4f992013-05-24 07:40:05 -04001737 switch (cifs_parse_devname(devname, vol)) {
1738 case 0:
1739 break;
1740 case -ENOMEM:
1741 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1742 goto cifs_parse_mount_err;
1743 case -EINVAL:
1744 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1745 goto cifs_parse_mount_err;
1746 default:
1747 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1748 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001749 }
1750
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001752 substring_t args[MAX_OPT_ARGS];
1753 unsigned long option;
1754 int token;
1755
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 if (!*data)
1757 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001759 token = match_token(data, cifs_mount_option_tokens, args);
1760
1761 switch (token) {
1762
1763 /* Ingnore the following */
1764 case Opt_ignore:
1765 break;
1766
1767 /* Boolean values */
1768 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001770 break;
1771 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001773 break;
1774 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001775 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001776 break;
1777 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001778 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001779 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001780 case Opt_forcegid:
1781 override_gid = 1;
1782 break;
1783 case Opt_noforcegid:
1784 override_gid = 0;
1785 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001786 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001787 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001788 break;
1789 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001790 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001791 break;
Steve French3e7a02d2019-09-11 21:46:20 -05001792 case Opt_nolease:
1793 vol->no_lease = 1;
1794 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001795 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001797 break;
1798 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001800 break;
1801 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 break;
1804 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001806 break;
1807 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001808 vol->sfu_remap = true;
1809 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001810 break;
1811 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001812 vol->sfu_remap = false;
1813 break;
1814 case Opt_mapposix:
1815 vol->remap = true;
1816 vol->sfu_remap = false; /* disable SFU mapping */
1817 break;
1818 case Opt_nomapposix:
1819 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001820 break;
1821 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001822 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001823 break;
1824 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001825 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001826 break;
1827 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001828 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001829 break;
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03001830 case Opt_rootfs:
1831#ifdef CONFIG_CIFS_ROOT
1832 vol->rootfs = true;
1833#endif
1834 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001835 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001836 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001837 break;
1838 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001839 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001840 break;
1841 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001842 if (vol->linux_ext)
1843 cifs_dbg(VFS,
1844 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001845 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001846 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001847 case Opt_unix:
1848 if (vol->no_linux_ext)
1849 cifs_dbg(VFS,
1850 "conflicting unix mount options\n");
1851 vol->linux_ext = 1;
1852 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001853 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001854 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001855 break;
1856 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001857 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001858 break;
1859 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001860 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001861 /*
1862 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001863 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001864 * local vfs will do advisory
1865 */
Steve French50c2f752007-07-13 00:33:32 +00001866 if (vol->file_mode ==
1867 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001868 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001869 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001870 case Opt_nohandlecache:
1871 vol->nohandlecache = 1;
1872 break;
1873 case Opt_handlecache:
1874 vol->nohandlecache = 0;
1875 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001876 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001877 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001878 break;
1879 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001881 break;
1882 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001884 break;
Steve French95932652016-09-23 01:36:34 -05001885 case Opt_setuidfromacl:
1886 vol->setuidfromacl = 1;
1887 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001888 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001889 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001890 break;
1891 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001892 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001893 break;
1894 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001896 break;
1897 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001899 break;
1900 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001902 break;
1903 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001905 break;
1906 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001907 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001908 break;
1909 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001910 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001911 break;
1912 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001914 break;
1915 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001917 break;
1918 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001919 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001920 break;
Steve French412094a2019-06-24 02:01:42 -05001921 case Opt_modesid:
1922 vol->mode_ace = 1;
1923 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001924 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001925 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001926 break;
1927 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001928 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001929 break;
1930 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001932 break;
1933 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001935 break;
1936 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001937 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001938 break;
1939 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001940 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001941 break;
Steve French4f5c10f2019-09-03 21:18:49 -05001942 case Opt_ignore_signature:
1943 vol->sign = true;
1944 vol->ignore_signature = true;
1945 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001946 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001947 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001948 * is a per tree connection (mount) not a per socket
1949 * or per-smb connection option in the protocol
1950 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1951 */
Steve French95b1cb92008-05-15 16:44:38 +00001952 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001953 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001954 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001955 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001956 break;
1957 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301958#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001959 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001960 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301961#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301962 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001963 break;
1964 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001965 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001966 break;
1967 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001968 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001969 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001970 case Opt_sloppy:
1971 sloppy = true;
1972 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001973 case Opt_nosharesock:
1974 vol->nosharesock = true;
1975 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001976 case Opt_nopersistent:
1977 vol->nopersistent = true;
1978 if (vol->persistent) {
1979 cifs_dbg(VFS,
1980 "persistenthandles mount options conflict\n");
1981 goto cifs_parse_mount_err;
1982 }
1983 break;
1984 case Opt_persistent:
1985 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001986 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001987 cifs_dbg(VFS,
1988 "persistenthandles mount options conflict\n");
1989 goto cifs_parse_mount_err;
1990 }
1991 break;
Steve French592fafe2015-11-03 10:08:53 -06001992 case Opt_resilient:
1993 vol->resilient = true;
1994 if (vol->persistent) {
1995 cifs_dbg(VFS,
1996 "persistenthandles mount options conflict\n");
1997 goto cifs_parse_mount_err;
1998 }
1999 break;
2000 case Opt_noresilient:
2001 vol->resilient = false; /* already the default */
2002 break;
Germano Percossi39566442016-12-15 12:31:18 +05302003 case Opt_domainauto:
2004 vol->domainauto = true;
2005 break;
Long Li8339dd32017-11-07 01:54:55 -07002006 case Opt_rdma:
2007 vol->rdma = true;
2008 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002009 case Opt_multichannel:
2010 vol->multichannel = true;
2011 break;
2012 case Opt_nomultichannel:
2013 vol->multichannel = false;
2014 break;
Steve French9fe5ff12019-06-24 20:39:04 -05002015 case Opt_compress:
2016 vol->compression = UNKNOWN_TYPE;
2017 cifs_dbg(VFS,
2018 "SMB3 compression support is experimental\n");
2019 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002020
2021 /* Numeric Values */
2022 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002023 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002024 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
2025 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05002026 goto cifs_parse_mount_err;
2027 }
2028 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002029 break;
2030 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002031 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002032 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
2033 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05002034 goto cifs_parse_mount_err;
2035 }
2036 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002037 break;
2038 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002039 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002040 cifs_dbg(VFS, "%s: Invalid uid value\n",
2041 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00002042 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002044 uid_specified = true;
2045 break;
2046 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002047 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002048 cifs_dbg(VFS, "%s: Invalid cruid value\n",
2049 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002050 goto cifs_parse_mount_err;
2051 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002052 break;
2053 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002054 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002055 cifs_dbg(VFS, "%s: Invalid gid value\n",
2056 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002057 goto cifs_parse_mount_err;
2058 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002059 gid_specified = true;
2060 break;
2061 case Opt_file_mode:
2062 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002063 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
2064 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002065 goto cifs_parse_mount_err;
2066 }
2067 vol->file_mode = option;
2068 break;
2069 case Opt_dirmode:
2070 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002071 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
2072 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002073 goto cifs_parse_mount_err;
2074 }
2075 vol->dir_mode = option;
2076 break;
2077 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002078 if (get_option_ul(args, &option) ||
2079 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002080 cifs_dbg(VFS, "%s: Invalid port value\n",
2081 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002082 goto cifs_parse_mount_err;
2083 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002084 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002085 break;
Steve French563317e2019-09-08 23:22:02 -05002086 case Opt_min_enc_offload:
2087 if (get_option_ul(args, &option)) {
2088 cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
2089 goto cifs_parse_mount_err;
2090 }
2091 vol->min_offload = option;
2092 break;
Steve Frenche8506d22019-02-28 21:32:15 -06002093 case Opt_blocksize:
2094 if (get_option_ul(args, &option)) {
2095 cifs_dbg(VFS, "%s: Invalid blocksize value\n",
2096 __func__);
2097 goto cifs_parse_mount_err;
2098 }
2099 /*
2100 * inode blocksize realistically should never need to be
2101 * less than 16K or greater than 16M and default is 1MB.
2102 * Note that small inode block sizes (e.g. 64K) can lead
2103 * to very poor performance of common tools like cp and scp
2104 */
2105 if ((option < CIFS_MAX_MSGSIZE) ||
2106 (option > (4 * SMB3_DEFAULT_IOSIZE))) {
2107 cifs_dbg(VFS, "%s: Invalid blocksize\n",
2108 __func__);
2109 goto cifs_parse_mount_err;
2110 }
2111 vol->bsize = option;
2112 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002113 case Opt_rsize:
2114 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002115 cifs_dbg(VFS, "%s: Invalid rsize value\n",
2116 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002117 goto cifs_parse_mount_err;
2118 }
2119 vol->rsize = option;
2120 break;
2121 case Opt_wsize:
2122 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002123 cifs_dbg(VFS, "%s: Invalid wsize value\n",
2124 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002125 goto cifs_parse_mount_err;
2126 }
2127 vol->wsize = option;
2128 break;
2129 case Opt_actimeo:
2130 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002131 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
2132 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002133 goto cifs_parse_mount_err;
2134 }
2135 vol->actimeo = HZ * option;
2136 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002137 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002138 goto cifs_parse_mount_err;
2139 }
2140 break;
Steve Frenchca567eb2019-03-29 16:31:07 -05002141 case Opt_handletimeout:
2142 if (get_option_ul(args, &option)) {
2143 cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
2144 __func__);
2145 goto cifs_parse_mount_err;
2146 }
2147 vol->handle_timeout = option;
2148 if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
2149 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
2150 goto cifs_parse_mount_err;
2151 }
2152 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002153 case Opt_echo_interval:
2154 if (get_option_ul(args, &option)) {
2155 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
2156 __func__);
2157 goto cifs_parse_mount_err;
2158 }
2159 vol->echo_interval = option;
2160 break;
Steve French8b217fe2016-11-11 22:36:20 -06002161 case Opt_snapshot:
2162 if (get_option_ul(args, &option)) {
2163 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
2164 __func__);
2165 goto cifs_parse_mount_err;
2166 }
2167 vol->snapshot_time = option;
2168 break;
Steve French141891f2016-09-23 00:44:16 -05002169 case Opt_max_credits:
2170 if (get_option_ul(args, &option) || (option < 20) ||
2171 (option > 60000)) {
2172 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
2173 __func__);
2174 goto cifs_parse_mount_err;
2175 }
2176 vol->max_credits = option;
2177 break;
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002178 case Opt_max_channels:
2179 if (get_option_ul(args, &option) || option < 1 ||
2180 option > CIFS_MAX_CHANNELS) {
2181 cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
2182 __func__, CIFS_MAX_CHANNELS);
2183 goto cifs_parse_mount_err;
2184 }
2185 vol->max_channels = option;
2186 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002187
2188 /* String Arguments */
2189
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002190 case Opt_blank_user:
2191 /* null user, ie. anonymous authentication */
2192 vol->nullauth = 1;
2193 vol->username = NULL;
2194 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002195 case Opt_user:
2196 string = match_strdup(args);
2197 if (string == NULL)
2198 goto out_nomem;
2199
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002200 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
2201 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002202 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002203 goto cifs_parse_mount_err;
2204 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002205
2206 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002207 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05002208 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002209 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002210 break;
2211 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002212 /* passwords have to be handled differently
2213 * to allow the character used for deliminator
2214 * to be passed within them
2215 */
2216
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002217 /*
2218 * Check if this is a case where the password
2219 * starts with a delimiter
2220 */
2221 tmp_end = strchr(data, '=');
2222 tmp_end++;
2223 if (!(tmp_end < end && tmp_end[1] == delim)) {
2224 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002225 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002226 vol->password = NULL;
2227 break;
2228 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +11002229 /* Fallthrough - to Opt_pass below.*/
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002230 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002231 /* Obtain the value string */
2232 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002233 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002234
2235 /* Set tmp_end to end of the string */
2236 tmp_end = (char *) value + strlen(value);
2237
2238 /* Check if following character is the deliminator
2239 * If yes, we have encountered a double deliminator
2240 * reset the NULL character to the deliminator
2241 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302242 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002243 tmp_end[0] = delim;
2244
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302245 /* Keep iterating until we get to a single
2246 * deliminator OR the end
2247 */
2248 while ((tmp_end = strchr(tmp_end, delim))
2249 != NULL && (tmp_end[1] == delim)) {
2250 tmp_end = (char *) &tmp_end[2];
2251 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002252
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302253 /* Reset var options to point to next element */
2254 if (tmp_end) {
2255 tmp_end[0] = '\0';
2256 options = (char *) &tmp_end[1];
2257 } else
2258 /* Reached the end of the mount option
2259 * string */
2260 options = end;
2261 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002262
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002263 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002264 /* Now build new password string */
2265 temp_len = strlen(value);
2266 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2267 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002268 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002269 goto cifs_parse_mount_err;
2270 }
2271
2272 for (i = 0, j = 0; i < temp_len; i++, j++) {
2273 vol->password[j] = value[i];
2274 if ((value[i] == delim) &&
2275 value[i+1] == delim)
2276 /* skip the second deliminator */
2277 i++;
2278 }
2279 vol->password[j] = '\0';
2280 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002281 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002282 /* FIXME: should this be an error instead? */
2283 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002284 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002285 case Opt_ip:
2286 string = match_strdup(args);
2287 if (string == NULL)
2288 goto out_nomem;
2289
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002290 if (!cifs_convert_address(dstaddr, string,
2291 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002292 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002293 goto cifs_parse_mount_err;
2294 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002295 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002296 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002297 case Opt_domain:
2298 string = match_strdup(args);
2299 if (string == NULL)
2300 goto out_nomem;
2301
Chen Gang057d6332013-07-19 09:01:36 +08002302 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2303 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002304 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002305 goto cifs_parse_mount_err;
2306 }
2307
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002308 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002309 vol->domainname = kstrdup(string, GFP_KERNEL);
2310 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002311 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002312 goto cifs_parse_mount_err;
2313 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002314 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002315 break;
2316 case Opt_srcaddr:
2317 string = match_strdup(args);
2318 if (string == NULL)
2319 goto out_nomem;
2320
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002321 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002322 (struct sockaddr *)&vol->srcaddr,
2323 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002324 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2325 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002326 goto cifs_parse_mount_err;
2327 }
2328 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002329 case Opt_iocharset:
2330 string = match_strdup(args);
2331 if (string == NULL)
2332 goto out_nomem;
2333
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002334 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002335 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002336 goto cifs_parse_mount_err;
2337 }
2338
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002339 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002340 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002341 vol->iocharset = kstrdup(string,
2342 GFP_KERNEL);
2343 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002344 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002345 goto cifs_parse_mount_err;
2346 }
2347 }
2348 /* if iocharset not set then load_nls_default
2349 * is used by caller
2350 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002351 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002352 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002353 case Opt_netbiosname:
2354 string = match_strdup(args);
2355 if (string == NULL)
2356 goto out_nomem;
2357
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002358 memset(vol->source_rfc1001_name, 0x20,
2359 RFC1001_NAME_LEN);
2360 /*
2361 * FIXME: are there cases in which a comma can
2362 * be valid in workstation netbios name (and
2363 * need special handling)?
2364 */
2365 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2366 /* don't ucase netbiosname for user */
2367 if (string[i] == 0)
2368 break;
2369 vol->source_rfc1001_name[i] = string[i];
2370 }
2371 /* The string has 16th byte zero still from
2372 * set at top of the function
2373 */
2374 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002375 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002376 break;
2377 case Opt_servern:
2378 /* servernetbiosname specified override *SMBSERVER */
2379 string = match_strdup(args);
2380 if (string == NULL)
2381 goto out_nomem;
2382
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002383 /* last byte, type, is 0x20 for servr type */
2384 memset(vol->target_rfc1001_name, 0x20,
2385 RFC1001_NAME_LEN_WITH_NULL);
2386
2387 /* BB are there cases in which a comma can be
2388 valid in this workstation netbios name
2389 (and need special handling)? */
2390
2391 /* user or mount helper must uppercase the
2392 netbios name */
2393 for (i = 0; i < 15; i++) {
2394 if (string[i] == 0)
2395 break;
2396 vol->target_rfc1001_name[i] = string[i];
2397 }
2398 /* The string has 16th byte zero still from
2399 set at top of the function */
2400 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002401 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002402 break;
2403 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002404 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002405 string = match_strdup(args);
2406 if (string == NULL)
2407 goto out_nomem;
2408
Steve French7e682f72017-08-31 21:34:24 -05002409 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002410 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002411 if (strlen(string) > 1) {
2412 pr_warn("Bad mount helper ver=%s. Did "
2413 "you want SMB1 (CIFS) dialect "
2414 "and mean to type vers=1.0 "
2415 "instead?\n", string);
2416 goto cifs_parse_mount_err;
2417 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002418 /* This is the default */
2419 break;
2420 }
2421 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05002422 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002423 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002424 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002425 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002426 string = match_strdup(args);
2427 if (string == NULL)
2428 goto out_nomem;
2429
Steve Frenchc7c137b2018-06-06 17:59:29 -05002430 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002431 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002432 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002433 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002434 case Opt_sec:
2435 string = match_strdup(args);
2436 if (string == NULL)
2437 goto out_nomem;
2438
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002439 if (cifs_parse_security_flavors(string, vol) != 0)
2440 goto cifs_parse_mount_err;
2441 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002442 case Opt_cache:
2443 string = match_strdup(args);
2444 if (string == NULL)
2445 goto out_nomem;
2446
2447 if (cifs_parse_cache_flavor(string, vol) != 0)
2448 goto cifs_parse_mount_err;
2449 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002450 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002451 /*
2452 * An option we don't recognize. Save it off for later
2453 * if we haven't already found one
2454 */
2455 if (!invalid)
2456 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002457 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002459 /* Free up any allocated string */
2460 kfree(string);
2461 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002463
Jeff Laytond8162552012-03-23 14:40:56 -04002464 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002465 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002466 goto cifs_parse_mount_err;
2467 }
2468
Long Li8339dd32017-11-07 01:54:55 -07002469 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2470 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2471 goto cifs_parse_mount_err;
2472 }
2473
Jeff Layton8a8798a2012-01-17 16:09:15 -05002474#ifndef CONFIG_KEYS
2475 /* Muliuser mounts require CONFIG_KEYS support */
2476 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002477 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002478 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002479 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002480#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002481 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002482 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002483 goto cifs_parse_mount_err;
2484 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002485
Jeff Layton62a1a432012-12-10 06:10:45 -05002486 /* make sure UNC has a share name */
2487 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002488 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002489 goto cifs_parse_mount_err;
2490 }
2491
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002492 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002493 int len;
2494 const char *slash;
2495
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002496 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002497 /* Use the address part of the UNC. */
2498 slash = strchr(&vol->UNC[2], '\\');
2499 len = slash - &vol->UNC[2];
2500 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002501 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002502 goto cifs_parse_mount_err;
2503 }
2504 }
2505
2506 /* set the port that we got earlier */
2507 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002509 if (uid_specified)
2510 vol->override_uid = override_uid;
2511 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002512 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002513
2514 if (gid_specified)
2515 vol->override_gid = override_gid;
2516 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002517 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002518
Steve French7e682f72017-08-31 21:34:24 -05002519 if (got_version == false)
2520 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002521 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002522 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002523 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2524 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002525
Sean Finneyb9468452011-04-11 13:19:32 +00002526 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002528
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002529out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002530 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002531cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002532 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002533 kfree(mountdata_copy);
2534 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535}
2536
Ben Greear3eb9a882010-09-01 17:06:02 -07002537/** Returns true if srcaddr isn't specified and rhs isn't
2538 * specified, or if srcaddr is specified and
2539 * matches the IP address of the rhs argument.
2540 */
Jeff Layton45151482010-07-06 20:43:02 -04002541static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002542srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2543{
2544 switch (srcaddr->sa_family) {
2545 case AF_UNSPEC:
2546 return (rhs->sa_family == AF_UNSPEC);
2547 case AF_INET: {
2548 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2549 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2550 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2551 }
2552 case AF_INET6: {
2553 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002554 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002555 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2556 }
2557 default:
2558 WARN_ON(1);
2559 return false; /* don't expect to be here */
2560 }
2561}
2562
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002563/*
2564 * If no port is specified in addr structure, we try to match with 445 port
2565 * and if it fails - with 139 ports. It should be called only if address
2566 * families of server and addr are equal.
2567 */
2568static bool
2569match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2570{
Steve French6da97912011-03-13 18:55:55 +00002571 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002572
Long Li3b249112019-05-15 14:09:04 -07002573 /* SMBDirect manages its own ports, don't match it here */
2574 if (server->rdma)
2575 return true;
2576
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002577 switch (addr->sa_family) {
2578 case AF_INET:
2579 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2580 port = ((struct sockaddr_in *) addr)->sin_port;
2581 break;
2582 case AF_INET6:
2583 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2584 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2585 break;
2586 default:
2587 WARN_ON(1);
2588 return false;
2589 }
2590
2591 if (!port) {
2592 port = htons(CIFS_PORT);
2593 if (port == *sport)
2594 return true;
2595
2596 port = htons(RFC1001_PORT);
2597 }
2598
2599 return port == *sport;
2600}
Ben Greear3eb9a882010-09-01 17:06:02 -07002601
2602static bool
2603match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2604 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605{
Jeff Layton45151482010-07-06 20:43:02 -04002606 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002607 case AF_INET: {
2608 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2609 struct sockaddr_in *srv_addr4 =
2610 (struct sockaddr_in *)&server->dstaddr;
2611
2612 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002613 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002614 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002615 }
2616 case AF_INET6: {
2617 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2618 struct sockaddr_in6 *srv_addr6 =
2619 (struct sockaddr_in6 *)&server->dstaddr;
2620
Jeff Layton45151482010-07-06 20:43:02 -04002621 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002622 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002623 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002624 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002625 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002626 break;
2627 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002628 default:
2629 WARN_ON(1);
2630 return false; /* don't expect to be here */
2631 }
Jeff Layton45151482010-07-06 20:43:02 -04002632
Ben Greear3eb9a882010-09-01 17:06:02 -07002633 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2634 return false;
2635
Jeff Layton45151482010-07-06 20:43:02 -04002636 return true;
2637}
2638
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002639static bool
2640match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2641{
Jeff Layton3f618222013-06-12 19:52:14 -05002642 /*
2643 * The select_sectype function should either return the vol->sectype
2644 * that was specified, or "Unspecified" if that sectype was not
2645 * compatible with the given NEGOTIATE request.
2646 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302647 if (server->ops->select_sectype(server, vol->sectype)
2648 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002649 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002650
Jeff Layton3f618222013-06-12 19:52:14 -05002651 /*
2652 * Now check if signing mode is acceptable. No need to check
2653 * global_secflags at this point since if MUST_SIGN is set then
2654 * the server->sign had better be too.
2655 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002656 if (vol->sign && !server->sign)
2657 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002658
2659 return true;
2660}
2661
Jeff Layton9fa114f2012-11-26 11:09:57 -05002662static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002663{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002664 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2665
Jeff Laytona0b3df52013-05-24 07:40:59 -04002666 if (vol->nosharesock)
2667 return 0;
2668
Steve French43cdae82019-06-13 14:26:49 -05002669 /* If multidialect negotiation see if existing sessions match one */
2670 if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2671 if (server->vals->protocol_id < SMB30_PROT_ID)
2672 return 0;
2673 } else if (strcmp(vol->vals->version_string,
2674 SMBDEFAULT_VERSION_STRING) == 0) {
2675 if (server->vals->protocol_id < SMB21_PROT_ID)
2676 return 0;
2677 } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
Jeff Layton23db65f2012-05-15 12:20:51 -04002678 return 0;
2679
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002680 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2681 return 0;
2682
2683 if (!match_address(server, addr,
2684 (struct sockaddr *)&vol->srcaddr))
2685 return 0;
2686
2687 if (!match_port(server, addr))
2688 return 0;
2689
2690 if (!match_security(server, vol))
2691 return 0;
2692
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002693 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002694 return 0;
2695
Long Li8339dd32017-11-07 01:54:55 -07002696 if (server->rdma != vol->rdma)
2697 return 0;
2698
Steve French4f5c10f2019-09-03 21:18:49 -05002699 if (server->ignore_signature != vol->ignore_signature)
2700 return 0;
2701
Steve French563317e2019-09-08 23:22:02 -05002702 if (server->min_offload != vol->min_offload)
2703 return 0;
2704
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002705 return 1;
2706}
2707
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002708struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002709cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002710{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002711 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302713 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002714 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002715 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002716 continue;
2717
Jeff Laytone7ddee92008-11-14 13:44:38 -05002718 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302719 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002720 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002721 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302723 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 return NULL;
2725}
2726
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002727void
2728cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002730 struct task_struct *task;
2731
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302732 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002733 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302734 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002735 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002737
Rob Landleyf1d0c992011-01-22 15:44:05 -06002738 put_net(cifs_net_ns(server));
2739
Jeff Laytone7ddee92008-11-14 13:44:38 -05002740 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302741 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002742
Jeff Laytonc74093b2011-01-11 07:24:23 -05002743 cancel_delayed_work_sync(&server->echo);
2744
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002745 if (from_reconnect)
2746 /*
2747 * Avoid deadlock here: reconnect work calls
2748 * cifs_put_tcp_session() at its end. Need to be sure
2749 * that reconnect work does nothing with server pointer after
2750 * that step.
2751 */
2752 cancel_delayed_work(&server->reconnect);
2753 else
2754 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002755
Jeff Laytone7ddee92008-11-14 13:44:38 -05002756 spin_lock(&GlobalMid_Lock);
2757 server->tcpStatus = CifsExiting;
2758 spin_unlock(&GlobalMid_Lock);
2759
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002760 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302761 cifs_fscache_release_client_cookie(server);
2762
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002763 kfree(server->session_key.response);
2764 server->session_key.response = NULL;
2765 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002766
2767 task = xchg(&server->tsk, NULL);
2768 if (task)
Eric W. Biederman72abe3b2019-05-15 12:33:50 -05002769 send_sig(SIGKILL, task, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770}
2771
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02002772struct TCP_Server_Info *
Jeff Layton63c038c2008-12-01 18:41:46 -05002773cifs_get_tcp_session(struct smb_vol *volume_info)
2774{
2775 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002776 int rc;
2777
Joe Perchesf96637b2013-05-04 22:12:25 -05002778 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002779
2780 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002781 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002782 if (tcp_ses)
2783 return tcp_ses;
2784
2785 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2786 if (!tcp_ses) {
2787 rc = -ENOMEM;
2788 goto out_err;
2789 }
2790
Jeff Layton23db65f2012-05-15 12:20:51 -04002791 tcp_ses->ops = volume_info->ops;
2792 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002793 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002794 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2795 if (IS_ERR(tcp_ses->hostname)) {
2796 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002797 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002798 }
2799
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03002800 tcp_ses->noblockcnt = volume_info->rootfs;
2801 tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
Jeff Layton63c038c2008-12-01 18:41:46 -05002802 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002803 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002804 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002805 tcp_ses->in_flight = 0;
Steve French1b63f182019-09-09 22:57:11 -05002806 tcp_ses->max_in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002807 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002808 init_waitqueue_head(&tcp_ses->response_q);
2809 init_waitqueue_head(&tcp_ses->request_q);
2810 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2811 mutex_init(&tcp_ses->srv_mutex);
2812 memcpy(tcp_ses->workstation_RFC1001_name,
2813 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2814 memcpy(tcp_ses->server_RFC1001_name,
2815 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002816 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002817 tcp_ses->sequence_number = 0;
Pavel Shilovsky5b964852019-01-18 11:30:26 -08002818 tcp_ses->reconnect_instance = 1;
Steve Frenchfda35942011-01-20 18:06:34 +00002819 tcp_ses->lstrp = jiffies;
Steve French9fe5ff12019-06-24 20:39:04 -05002820 tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
Jeff Layton58fa0152012-05-01 17:41:16 -04002821 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002822 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2823 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002824 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002825 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2826 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002827 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2828 sizeof(tcp_ses->srcaddr));
2829 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2830 sizeof(tcp_ses->dstaddr));
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002831 if (volume_info->use_client_guid)
2832 memcpy(tcp_ses->client_guid, volume_info->client_guid,
2833 SMB2_CLIENT_GUID_SIZE);
2834 else
2835 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002836 /*
2837 * at this point we are the only ones with the pointer
2838 * to the struct since the kernel thread not created yet
2839 * no need to spinlock this init of tcpStatus or srv_count
2840 */
2841 tcp_ses->tcpStatus = CifsNew;
2842 ++tcp_ses->srv_count;
2843
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002844 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2845 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2846 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2847 else
2848 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002849 if (tcp_ses->rdma) {
2850#ifndef CONFIG_CIFS_SMB_DIRECT
2851 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2852 rc = -ENOENT;
2853 goto out_err_crypto_release;
2854#endif
2855 tcp_ses->smbd_conn = smbd_get_connection(
2856 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2857 if (tcp_ses->smbd_conn) {
2858 cifs_dbg(VFS, "RDMA transport established\n");
2859 rc = 0;
2860 goto smbd_connected;
2861 } else {
2862 rc = -ENOENT;
2863 goto out_err_crypto_release;
2864 }
2865 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002866 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002867 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002868 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002869 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002870 }
Long Li2f894642017-11-22 17:38:34 -07002871smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002872 /*
2873 * since we're in a cifs function already, we know that
2874 * this will succeed. No need for try_module_get().
2875 */
2876 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002877 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002878 tcp_ses, "cifsd");
2879 if (IS_ERR(tcp_ses->tsk)) {
2880 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002881 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002882 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002883 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002884 }
Steve French563317e2019-09-08 23:22:02 -05002885 tcp_ses->min_offload = volume_info->min_offload;
Steve Frenchfd88ce92011-04-12 01:01:14 +00002886 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002887
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002888 tcp_ses->nr_targets = 1;
Steve French4f5c10f2019-09-03 21:18:49 -05002889 tcp_ses->ignore_signature = volume_info->ignore_signature;
Jeff Layton63c038c2008-12-01 18:41:46 -05002890 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302891 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002892 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302893 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002894
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302895 cifs_fscache_get_client_cookie(tcp_ses);
2896
Jeff Laytonc74093b2011-01-11 07:24:23 -05002897 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002898 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002899
Jeff Layton63c038c2008-12-01 18:41:46 -05002900 return tcp_ses;
2901
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002902out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002903 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002904
Rob Landleyf1d0c992011-01-22 15:44:05 -06002905 put_net(cifs_net_ns(tcp_ses));
2906
Jeff Layton63c038c2008-12-01 18:41:46 -05002907out_err:
2908 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002909 if (!IS_ERR(tcp_ses->hostname))
2910 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002911 if (tcp_ses->ssocket)
2912 sock_release(tcp_ses->ssocket);
2913 kfree(tcp_ses);
2914 }
2915 return ERR_PTR(rc);
2916}
2917
Steve French96daf2b2011-05-27 04:34:02 +00002918static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002919{
Jeff Layton3f618222013-06-12 19:52:14 -05002920 if (vol->sectype != Unspecified &&
2921 vol->sectype != ses->sectype)
2922 return 0;
2923
Aurelien Aptelbcc88802019-09-20 04:32:20 +02002924 /*
2925 * If an existing session is limited to less channels than
2926 * requested, it should not be reused
2927 */
2928 if (ses->chan_max < vol->max_channels)
2929 return 0;
2930
Jeff Layton3f618222013-06-12 19:52:14 -05002931 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002932 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002933 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002934 return 0;
2935 break;
2936 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002937 /* NULL username means anonymous session */
2938 if (ses->user_name == NULL) {
2939 if (!vol->nullauth)
2940 return 0;
2941 break;
2942 }
2943
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002944 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002945 if (strncmp(ses->user_name,
2946 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002947 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002948 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002949 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002950 ses->password != NULL &&
2951 strncmp(ses->password,
2952 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002953 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002954 return 0;
2955 }
2956 return 1;
2957}
2958
Aurelien Aptelb327a712018-01-24 13:46:10 +01002959/**
2960 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2961 *
2962 * A new IPC connection is made and stored in the session
2963 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2964 */
2965static int
2966cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2967{
2968 int rc = 0, xid;
2969 struct cifs_tcon *tcon;
2970 struct nls_table *nls_codepage;
2971 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2972 bool seal = false;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002973 struct TCP_Server_Info *server = ses->server;
Aurelien Aptelb327a712018-01-24 13:46:10 +01002974
2975 /*
2976 * If the mount request that resulted in the creation of the
2977 * session requires encryption, force IPC to be encrypted too.
2978 */
2979 if (volume_info->seal) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002980 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
Aurelien Aptelb327a712018-01-24 13:46:10 +01002981 seal = true;
2982 else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002983 cifs_server_dbg(VFS,
Aurelien Aptelb327a712018-01-24 13:46:10 +01002984 "IPC: server doesn't support encryption\n");
2985 return -EOPNOTSUPP;
2986 }
2987 }
2988
2989 tcon = tconInfoAlloc();
2990 if (tcon == NULL)
2991 return -ENOMEM;
2992
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002993 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002994
2995 /* cannot fail */
2996 nls_codepage = load_nls_default();
2997
2998 xid = get_xid();
2999 tcon->ses = ses;
3000 tcon->ipc = true;
3001 tcon->seal = seal;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003002 rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003003 free_xid(xid);
3004
3005 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003006 cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003007 tconInfoFree(tcon);
3008 goto out;
3009 }
3010
3011 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
3012
3013 ses->tcon_ipc = tcon;
3014out:
3015 unload_nls(nls_codepage);
3016 return rc;
3017}
3018
3019/**
3020 * cifs_free_ipc - helper to release the session IPC tcon
3021 *
3022 * Needs to be called everytime a session is destroyed
3023 */
3024static int
3025cifs_free_ipc(struct cifs_ses *ses)
3026{
3027 int rc = 0, xid;
3028 struct cifs_tcon *tcon = ses->tcon_ipc;
3029
3030 if (tcon == NULL)
3031 return 0;
3032
3033 if (ses->server->ops->tree_disconnect) {
3034 xid = get_xid();
3035 rc = ses->server->ops->tree_disconnect(xid, tcon);
3036 free_xid(xid);
3037 }
3038
3039 if (rc)
3040 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
3041
3042 tconInfoFree(tcon);
3043 ses->tcon_ipc = NULL;
3044 return rc;
3045}
3046
Steve French96daf2b2011-05-27 04:34:02 +00003047static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04003048cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049{
Steve French96daf2b2011-05-27 04:34:02 +00003050 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303052 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04003053 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003054 if (ses->status == CifsExiting)
3055 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003056 if (!match_session(ses, vol))
3057 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05003058 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303059 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003060 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303062 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 return NULL;
3064}
3065
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003066void cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05003067{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003068 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05003069 struct TCP_Server_Info *server = ses->server;
3070
Joe Perchesf96637b2013-05-04 22:12:25 -05003071 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003072
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303073 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003074 if (ses->status == CifsExiting) {
3075 spin_unlock(&cifs_tcp_ses_lock);
3076 return;
3077 }
Jeff Layton14fbf502008-11-14 13:53:46 -05003078 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303079 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003080 return;
3081 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003082 if (ses->status == CifsGood)
3083 ses->status = CifsExiting;
3084 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003085
Aurelien Aptelb327a712018-01-24 13:46:10 +01003086 cifs_free_ipc(ses);
3087
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003088 if (ses->status == CifsExiting && server->ops->logoff) {
3089 xid = get_xid();
3090 rc = server->ops->logoff(xid, ses);
3091 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003092 cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003093 __func__, rc);
3094 _free_xid(xid);
3095 }
3096
3097 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003098 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303099 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003100
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003101 /* close any extra channels */
3102 if (ses->chan_count > 1) {
3103 int i;
3104
3105 for (i = 1; i < ses->chan_count; i++)
3106 cifs_put_tcp_session(ses->chans[i].server, 0);
3107 }
3108
Jeff Layton14fbf502008-11-14 13:53:46 -05003109 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003110 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05003111}
3112
Jeff Layton8a8798a2012-01-17 16:09:15 -05003113#ifdef CONFIG_KEYS
3114
Chen Gang057d6332013-07-19 09:01:36 +08003115/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
3116#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05003117
3118/* Populate username and pw fields from keyring if possible */
3119static int
3120cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
3121{
3122 int rc = 0;
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003123 int is_domain = 0;
David Howells146aa8b2015-10-21 14:04:48 +01003124 const char *delim, *payload;
3125 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003126 ssize_t len;
3127 struct key *key;
3128 struct TCP_Server_Info *server = ses->server;
3129 struct sockaddr_in *sa;
3130 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01003131 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003132
3133 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
3134 if (!desc)
3135 return -ENOMEM;
3136
3137 /* try to find an address key first */
3138 switch (server->dstaddr.ss_family) {
3139 case AF_INET:
3140 sa = (struct sockaddr_in *)&server->dstaddr;
3141 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
3142 break;
3143 case AF_INET6:
3144 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
3145 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
3146 break;
3147 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05003148 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
3149 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003150 rc = -EINVAL;
3151 goto out_err;
3152 }
3153
Joe Perchesf96637b2013-05-04 22:12:25 -05003154 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003155 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003156 if (IS_ERR(key)) {
3157 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003158 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003159 rc = PTR_ERR(key);
3160 goto out_err;
3161 }
3162
3163 /* didn't work, try to find a domain key */
3164 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05003165 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003166 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003167 if (IS_ERR(key)) {
3168 rc = PTR_ERR(key);
3169 goto out_err;
3170 }
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003171 is_domain = 1;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003172 }
3173
3174 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00003175 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003176 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05003177 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003178 goto out_key_put;
3179 }
3180
3181 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01003182 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003183 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05003184 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003185 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003186 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
3187 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003188 rc = -EINVAL;
3189 goto out_key_put;
3190 }
3191
3192 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003193 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003194 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
3195 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003196 rc = -EINVAL;
3197 goto out_key_put;
3198 }
3199
3200 vol->username = kstrndup(payload, len, GFP_KERNEL);
3201 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003202 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
3203 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003204 rc = -ENOMEM;
3205 goto out_key_put;
3206 }
Joe Perchesf96637b2013-05-04 22:12:25 -05003207 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003208
3209 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003210 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003211 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003212 rc = -EINVAL;
3213 kfree(vol->username);
3214 vol->username = NULL;
3215 goto out_key_put;
3216 }
3217
3218 ++delim;
3219 vol->password = kstrndup(delim, len, GFP_KERNEL);
3220 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003221 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
3222 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003223 rc = -ENOMEM;
3224 kfree(vol->username);
3225 vol->username = NULL;
3226 goto out_key_put;
3227 }
3228
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003229 /*
3230 * If we have a domain key then we must set the domainName in the
3231 * for the request.
3232 */
3233 if (is_domain && ses->domainName) {
3234 vol->domainname = kstrndup(ses->domainName,
3235 strlen(ses->domainName),
3236 GFP_KERNEL);
3237 if (!vol->domainname) {
3238 cifs_dbg(FYI, "Unable to allocate %zd bytes for "
3239 "domain\n", len);
3240 rc = -ENOMEM;
3241 kfree(vol->username);
3242 vol->username = NULL;
Dan Carpenter478228e2019-08-27 13:59:17 +03003243 kzfree(vol->password);
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003244 vol->password = NULL;
3245 goto out_key_put;
3246 }
3247 }
3248
Jeff Layton8a8798a2012-01-17 16:09:15 -05003249out_key_put:
3250 up_read(&key->sem);
3251 key_put(key);
3252out_err:
3253 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05003254 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003255 return rc;
3256}
3257#else /* ! CONFIG_KEYS */
3258static inline int
3259cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
3260 struct cifs_ses *ses __attribute__((unused)))
3261{
3262 return -ENOSYS;
3263}
3264#endif /* CONFIG_KEYS */
3265
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003266/**
3267 * cifs_get_smb_ses - get a session matching @volume_info data from @server
3268 *
3269 * This function assumes it is being called from cifs_mount() where we
3270 * already got a server reference (server refcount +1). See
3271 * cifs_get_tcon() for refcount explanations.
3272 */
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003273struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04003274cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3275{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003276 int rc = -ENOMEM;
3277 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003278 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003279 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3280 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04003281
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003282 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04003283
Jeff Layton4ff67b72010-07-06 20:43:02 -04003284 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04003285 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003286 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3287 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04003288
Jeff Layton36988c72010-04-24 07:57:43 -04003289 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003290 rc = cifs_negotiate_protocol(xid, ses);
3291 if (rc) {
3292 mutex_unlock(&ses->session_mutex);
3293 /* problem -- put our ses reference */
3294 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003295 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003296 return ERR_PTR(rc);
3297 }
Jeff Layton36988c72010-04-24 07:57:43 -04003298 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003299 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003300 rc = cifs_setup_session(xid, ses,
3301 volume_info->local_nls);
3302 if (rc) {
3303 mutex_unlock(&ses->session_mutex);
3304 /* problem -- put our reference */
3305 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003306 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003307 return ERR_PTR(rc);
3308 }
3309 }
3310 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003311
3312 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003313 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003314 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003315 return ses;
3316 }
3317
Joe Perchesf96637b2013-05-04 22:12:25 -05003318 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003319 ses = sesInfoAlloc();
3320 if (ses == NULL)
3321 goto get_ses_fail;
3322
3323 /* new SMB session uses our server ref */
3324 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003325 if (server->dstaddr.ss_family == AF_INET6)
3326 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003327 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003328 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003329
Steve French8727c8a2011-02-25 01:11:56 -06003330 if (volume_info->username) {
3331 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3332 if (!ses->user_name)
3333 goto get_ses_fail;
3334 }
Jeff Layton36988c72010-04-24 07:57:43 -04003335
3336 /* volume_info->password freed at unmount */
3337 if (volume_info->password) {
3338 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3339 if (!ses->password)
3340 goto get_ses_fail;
3341 }
3342 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003343 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3344 if (!ses->domainName)
3345 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003346 }
Germano Percossi39566442016-12-15 12:31:18 +05303347 if (volume_info->domainauto)
3348 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003349 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003350 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003351
Jeff Layton28e11bd2013-05-26 07:01:00 -04003352 ses->sectype = volume_info->sectype;
3353 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003354 mutex_lock(&ses->session_mutex);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003355
3356 /* add server as first channel */
3357 ses->chans[0].server = server;
3358 ses->chan_count = 1;
3359 ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1;
3360
Jeff Layton198b5682010-04-24 07:57:48 -04003361 rc = cifs_negotiate_protocol(xid, ses);
3362 if (!rc)
3363 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003364
3365 /* each channel uses a different signing key */
3366 memcpy(ses->chans[0].signkey, ses->smb3signingkey,
3367 sizeof(ses->smb3signingkey));
3368
Jeff Layton36988c72010-04-24 07:57:43 -04003369 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003370 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003371 goto get_ses_fail;
3372
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02003373 /* success, put it on the list and add it as first channel */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303374 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003375 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303376 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003377
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003378 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003379
3380 cifs_setup_ipc(ses, volume_info);
3381
Jeff Layton36988c72010-04-24 07:57:43 -04003382 return ses;
3383
3384get_ses_fail:
3385 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003386 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003387 return ERR_PTR(rc);
3388}
3389
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003390static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003391{
3392 if (tcon->tidStatus == CifsExiting)
3393 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003394 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003395 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003396 if (tcon->seal != volume_info->seal)
3397 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003398 if (tcon->snapshot_time != volume_info->snapshot_time)
3399 return 0;
Steve Frenchca567eb2019-03-29 16:31:07 -05003400 if (tcon->handle_timeout != volume_info->handle_timeout)
3401 return 0;
Steve French3e7a02d2019-09-11 21:46:20 -05003402 if (tcon->no_lease != volume_info->no_lease)
3403 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003404 return 1;
3405}
3406
Steve French96daf2b2011-05-27 04:34:02 +00003407static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003408cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409{
3410 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003411 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303413 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003414 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003415 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003416 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003417 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003418 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303419 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420 return tcon;
3421 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303422 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423 return NULL;
3424}
3425
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003426void
Steve French96daf2b2011-05-27 04:34:02 +00003427cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003428{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003429 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003430 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003431
Aurelien Aptelb327a712018-01-24 13:46:10 +01003432 /*
3433 * IPC tcon share the lifetime of their session and are
3434 * destroyed in the session put function
3435 */
3436 if (tcon == NULL || tcon->ipc)
3437 return;
3438
3439 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003440 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303441 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003442 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303443 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003444 return;
3445 }
3446
3447 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303448 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003449
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003450 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003451 if (ses->server->ops->tree_disconnect)
3452 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003453 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003454
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303455 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003456 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003457 cifs_put_smb_ses(ses);
3458}
3459
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003460/**
3461 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3462 *
3463 * - tcon refcount is the number of mount points using the tcon.
3464 * - ses refcount is the number of tcon using the session.
3465 *
3466 * 1. This function assumes it is being called from cifs_mount() where
3467 * we already got a session reference (ses refcount +1).
3468 *
3469 * 2. Since we're in the context of adding a mount point, the end
3470 * result should be either:
3471 *
3472 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3473 * its session refcount incremented (1 new tcon). This +1 was
3474 * already done in (1).
3475 *
3476 * b) an existing tcon with refcount+1 (add a mount point to it) and
3477 * identical ses refcount (no new tcon). Because of (1) we need to
3478 * decrement the ses refcount.
3479 */
Steve French96daf2b2011-05-27 04:34:02 +00003480static struct cifs_tcon *
3481cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003482{
3483 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003484 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003485
Steve French8b217fe2016-11-11 22:36:20 -06003486 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003487 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003488 /*
3489 * tcon has refcount already incremented but we need to
3490 * decrement extra ses reference gotten by caller (case b)
3491 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003492 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003493 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003494 return tcon;
3495 }
3496
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003497 if (!ses->server->ops->tree_connect) {
3498 rc = -ENOSYS;
3499 goto out_fail;
3500 }
3501
Jeff Laytond00c28d2010-04-24 07:57:44 -04003502 tcon = tconInfoAlloc();
3503 if (tcon == NULL) {
3504 rc = -ENOMEM;
3505 goto out_fail;
3506 }
3507
Steve French8b217fe2016-11-11 22:36:20 -06003508 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003509 if (ses->server->vals->protocol_id == 0) {
3510 cifs_dbg(VFS,
3511 "Use SMB2 or later for snapshot mount option\n");
3512 rc = -EOPNOTSUPP;
3513 goto out_fail;
3514 } else
3515 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003516 }
3517
Steve Frenchca567eb2019-03-29 16:31:07 -05003518 if (volume_info->handle_timeout) {
3519 if (ses->server->vals->protocol_id == 0) {
3520 cifs_dbg(VFS,
3521 "Use SMB2.1 or later for handle timeout option\n");
3522 rc = -EOPNOTSUPP;
3523 goto out_fail;
3524 } else
3525 tcon->handle_timeout = volume_info->handle_timeout;
3526 }
3527
Jeff Laytond00c28d2010-04-24 07:57:44 -04003528 tcon->ses = ses;
3529 if (volume_info->password) {
3530 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3531 if (!tcon->password) {
3532 rc = -ENOMEM;
3533 goto out_fail;
3534 }
3535 }
3536
Steve French23657ad2018-04-22 15:14:58 -05003537 if (volume_info->seal) {
3538 if (ses->server->vals->protocol_id == 0) {
3539 cifs_dbg(VFS,
3540 "SMB3 or later required for encryption\n");
3541 rc = -EOPNOTSUPP;
3542 goto out_fail;
3543 } else if (tcon->ses->server->capabilities &
3544 SMB2_GLOBAL_CAP_ENCRYPTION)
3545 tcon->seal = true;
3546 else {
3547 cifs_dbg(VFS, "Encryption is not supported on share\n");
3548 rc = -EOPNOTSUPP;
3549 goto out_fail;
3550 }
3551 }
3552
Steve French8505c8b2018-06-18 14:01:59 -05003553 if (volume_info->linux_ext) {
3554 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003555 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003556 printk_once(KERN_WARNING
3557 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003558 } else {
3559 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3560 rc = -EOPNOTSUPP;
3561 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003562 }
Steve Frenchb3266142018-05-20 23:41:10 -05003563 }
Steve Frenchb3266142018-05-20 23:41:10 -05003564
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003565 /*
3566 * BB Do we need to wrap session_mutex around this TCon call and Unix
3567 * SetFS as we do on SessSetup and reconnect?
3568 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003569 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003570 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3571 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003572 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003573 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003574 if (rc)
3575 goto out_fail;
3576
Steve Frenchb618f002015-11-03 09:15:03 -06003577 tcon->use_persistent = false;
3578 /* check if SMB2 or later, CIFS does not support persistent handles */
3579 if (volume_info->persistent) {
3580 if (ses->server->vals->protocol_id == 0) {
3581 cifs_dbg(VFS,
3582 "SMB3 or later required for persistent handles\n");
3583 rc = -EOPNOTSUPP;
3584 goto out_fail;
3585 } else if (ses->server->capabilities &
3586 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3587 tcon->use_persistent = true;
3588 else /* persistent handles requested but not supported */ {
3589 cifs_dbg(VFS,
3590 "Persistent handles not supported on share\n");
3591 rc = -EOPNOTSUPP;
3592 goto out_fail;
3593 }
3594 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3595 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3596 && (volume_info->nopersistent == false)) {
3597 cifs_dbg(FYI, "enabling persistent handles\n");
3598 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003599 } else if (volume_info->resilient) {
3600 if (ses->server->vals->protocol_id == 0) {
3601 cifs_dbg(VFS,
3602 "SMB2.1 or later required for resilient handles\n");
3603 rc = -EOPNOTSUPP;
3604 goto out_fail;
3605 }
3606 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003607 }
3608
Steve Frenchcae53f72019-09-03 17:49:46 -05003609 /* If the user really knows what they are doing they can override */
3610 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3611 if (volume_info->cache_ro)
3612 cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3613 else if (volume_info->cache_rw)
3614 cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3615 }
3616
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003617 /*
3618 * We can have only one retry value for a connection to a share so for
3619 * resources mounted more than once to the same server share the last
3620 * value passed in for the retry flag is used.
3621 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003622 tcon->retry = volume_info->retry;
3623 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003624 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003625 tcon->local_lease = volume_info->local_lease;
Steve French3e7a02d2019-09-11 21:46:20 -05003626 tcon->no_lease = volume_info->no_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003627 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003628
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303629 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003630 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303631 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003632
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303633 cifs_fscache_get_super_cookie(tcon);
3634
Jeff Laytond00c28d2010-04-24 07:57:44 -04003635 return tcon;
3636
3637out_fail:
3638 tconInfoFree(tcon);
3639 return ERR_PTR(rc);
3640}
3641
Jeff Layton9d002df2010-10-06 19:51:11 -04003642void
3643cifs_put_tlink(struct tcon_link *tlink)
3644{
3645 if (!tlink || IS_ERR(tlink))
3646 return;
3647
3648 if (!atomic_dec_and_test(&tlink->tl_count) ||
3649 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3650 tlink->tl_time = jiffies;
3651 return;
3652 }
3653
3654 if (!IS_ERR(tlink_tcon(tlink)))
3655 cifs_put_tcon(tlink_tcon(tlink));
3656 kfree(tlink);
3657 return;
3658}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003659
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003660static int
3661compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3662{
3663 struct cifs_sb_info *old = CIFS_SB(sb);
3664 struct cifs_sb_info *new = mnt_data->cifs_sb;
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003665 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3666 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003667
3668 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3669 return 0;
3670
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003671 if (old->mnt_cifs_serverino_autodisabled)
3672 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3673
3674 if (oldflags != newflags)
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003675 return 0;
3676
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003677 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003678 * We want to share sb only if we don't specify an r/wsize or
3679 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003680 */
3681 if (new->wsize && new->wsize < old->wsize)
3682 return 0;
3683
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003684 if (new->rsize && new->rsize < old->rsize)
3685 return 0;
3686
Eric W. Biederman1f682332013-02-06 01:20:20 -08003687 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003688 return 0;
3689
3690 if (old->mnt_file_mode != new->mnt_file_mode ||
3691 old->mnt_dir_mode != new->mnt_dir_mode)
3692 return 0;
3693
3694 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3695 return 0;
3696
3697 if (old->actimeo != new->actimeo)
3698 return 0;
3699
3700 return 1;
3701}
3702
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003703static int
3704match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3705{
3706 struct cifs_sb_info *old = CIFS_SB(sb);
3707 struct cifs_sb_info *new = mnt_data->cifs_sb;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003708 bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3709 bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003710
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003711 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003712 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003713 else if (!old_set && !new_set)
3714 return 1;
3715
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003716 return 0;
3717}
3718
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003719int
3720cifs_match_super(struct super_block *sb, void *data)
3721{
3722 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3723 struct smb_vol *volume_info;
3724 struct cifs_sb_info *cifs_sb;
3725 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003726 struct cifs_ses *ses;
3727 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003728 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003729 int rc = 0;
3730
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003731 spin_lock(&cifs_tcp_ses_lock);
3732 cifs_sb = CIFS_SB(sb);
3733 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3734 if (IS_ERR(tlink)) {
3735 spin_unlock(&cifs_tcp_ses_lock);
3736 return rc;
3737 }
3738 tcon = tlink_tcon(tlink);
3739 ses = tcon->ses;
3740 tcp_srv = ses->server;
3741
3742 volume_info = mnt_data->vol;
3743
Jeff Layton9fa114f2012-11-26 11:09:57 -05003744 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003745 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003746 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003747 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003748 rc = 0;
3749 goto out;
3750 }
3751
3752 rc = compare_mount_options(sb, mnt_data);
3753out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003754 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003755 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003756 return rc;
3757}
3758
Jeff Layton09e50d52008-07-23 10:11:19 -04003759#ifdef CONFIG_DEBUG_LOCK_ALLOC
3760static struct lock_class_key cifs_key[2];
3761static struct lock_class_key cifs_slock_key[2];
3762
3763static inline void
3764cifs_reclassify_socket4(struct socket *sock)
3765{
3766 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003767 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003768 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3769 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3770}
3771
3772static inline void
3773cifs_reclassify_socket6(struct socket *sock)
3774{
3775 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003776 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003777 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3778 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3779}
3780#else
3781static inline void
3782cifs_reclassify_socket4(struct socket *sock)
3783{
3784}
3785
3786static inline void
3787cifs_reclassify_socket6(struct socket *sock)
3788{
3789}
3790#endif
3791
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003793static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794{
Steve French50c2f752007-07-13 00:33:32 +00003795 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
Steve French50c2f752007-07-13 00:33:32 +00003797 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798 /* mask a nibble at a time and encode */
3799 target[j] = 'A' + (0x0F & (source[i] >> 4));
3800 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003801 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 }
3803
3804}
3805
Ben Greear3eb9a882010-09-01 17:06:02 -07003806static int
3807bind_socket(struct TCP_Server_Info *server)
3808{
3809 int rc = 0;
3810 if (server->srcaddr.ss_family != AF_UNSPEC) {
3811 /* Bind to the specified local IP address */
3812 struct socket *socket = server->ssocket;
3813 rc = socket->ops->bind(socket,
3814 (struct sockaddr *) &server->srcaddr,
3815 sizeof(server->srcaddr));
3816 if (rc < 0) {
3817 struct sockaddr_in *saddr4;
3818 struct sockaddr_in6 *saddr6;
3819 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3820 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3821 if (saddr6->sin6_family == AF_INET6)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003822 cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003823 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003824 else
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003825 cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003826 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003827 }
3828 }
3829 return rc;
3830}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831
3832static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003833ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834{
3835 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003836 /*
3837 * some servers require RFC1001 sessinit before sending
3838 * negprot - BB check reconnection in case where second
3839 * sessinit is sent but no second negprot
3840 */
3841 struct rfc1002_session_packet *ses_init_buf;
3842 struct smb_hdr *smb_buf;
3843 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3844 GFP_KERNEL);
3845 if (ses_init_buf) {
3846 ses_init_buf->trailer.session_req.called_len = 32;
3847
Colin Ian King997152f2016-01-25 16:25:54 +00003848 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003849 rfc1002mangle(ses_init_buf->trailer.
3850 session_req.called_name,
3851 server->server_RFC1001_name,
3852 RFC1001_NAME_LEN_WITH_NULL);
3853 else
3854 rfc1002mangle(ses_init_buf->trailer.
3855 session_req.called_name,
3856 DEFAULT_CIFS_CALLED_NAME,
3857 RFC1001_NAME_LEN_WITH_NULL);
3858
3859 ses_init_buf->trailer.session_req.calling_len = 32;
3860
3861 /*
3862 * calling name ends in null (byte 16) from old smb
3863 * convention.
3864 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003865 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003866 rfc1002mangle(ses_init_buf->trailer.
3867 session_req.calling_name,
3868 server->workstation_RFC1001_name,
3869 RFC1001_NAME_LEN_WITH_NULL);
3870 else
3871 rfc1002mangle(ses_init_buf->trailer.
3872 session_req.calling_name,
3873 "LINUX_CIFS_CLNT",
3874 RFC1001_NAME_LEN_WITH_NULL);
3875
3876 ses_init_buf->trailer.session_req.scope1 = 0;
3877 ses_init_buf->trailer.session_req.scope2 = 0;
3878 smb_buf = (struct smb_hdr *)ses_init_buf;
3879
3880 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003881 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003882 rc = smb_send(server, smb_buf, 0x44);
3883 kfree(ses_init_buf);
3884 /*
3885 * RFC1001 layer in at least one server
3886 * requires very short break before negprot
3887 * presumably because not expecting negprot
3888 * to follow so fast. This is a simple
3889 * solution that works without
3890 * complicating the code and causes no
3891 * significant slowing down on mount
3892 * for everyone else
3893 */
3894 usleep_range(1000, 2000);
3895 }
3896 /*
3897 * else the negprot may still work without this
3898 * even though malloc failed
3899 */
3900
3901 return rc;
3902}
3903
3904static int
3905generic_ip_connect(struct TCP_Server_Info *server)
3906{
3907 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003908 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003909 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003910 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003911 struct sockaddr *saddr;
3912
3913 saddr = (struct sockaddr *) &server->dstaddr;
3914
3915 if (server->dstaddr.ss_family == AF_INET6) {
3916 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3917 slen = sizeof(struct sockaddr_in6);
3918 sfamily = AF_INET6;
3919 } else {
3920 sport = ((struct sockaddr_in *) saddr)->sin_port;
3921 slen = sizeof(struct sockaddr_in);
3922 sfamily = AF_INET;
3923 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003925 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003926 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3927 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 if (rc < 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003929 cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003930 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003933
3934 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003935 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003936 server->ssocket = socket;
3937 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003938 if (sfamily == AF_INET6)
3939 cifs_reclassify_socket6(socket);
3940 else
3941 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 }
3943
Ben Greear3eb9a882010-09-01 17:06:02 -07003944 rc = bind_socket(server);
3945 if (rc < 0)
3946 return rc;
3947
Jeff Laytond5c56052008-12-01 18:42:33 -05003948 /*
3949 * Eventually check for other socket options to change from
3950 * the default. sock_setsockopt not used because it expects
3951 * user space buffer
3952 */
3953 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003954 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003955
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003956 /* make the bufsizes depend on wsize/rsize and max requests */
3957 if (server->noautotune) {
3958 if (socket->sk->sk_sndbuf < (200 * 1024))
3959 socket->sk->sk_sndbuf = 200 * 1024;
3960 if (socket->sk->sk_rcvbuf < (140 * 1024))
3961 socket->sk->sk_rcvbuf = 140 * 1024;
3962 }
3963
Steve French6a5fa2362010-01-01 01:28:43 +00003964 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003965 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003966 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3967 (char *)&val, sizeof(val));
3968 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003969 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3970 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003971 }
3972
Joe Perchesf96637b2013-05-04 22:12:25 -05003973 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003974 socket->sk->sk_sndbuf,
3975 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3976
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003977 rc = socket->ops->connect(socket, saddr, slen,
3978 server->noblockcnt ? O_NONBLOCK : 0);
Paulo Alcantara (SUSE)d532cc72019-10-10 12:31:58 -03003979 /*
3980 * When mounting SMB root file systems, we do not want to block in
3981 * connect. Otherwise bail out and then let cifs_reconnect() perform
3982 * reconnect failover - if possible.
3983 */
3984 if (server->noblockcnt && rc == -EINPROGRESS)
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003985 rc = 0;
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003986 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003987 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003988 sock_release(socket);
3989 server->ssocket = NULL;
3990 return rc;
3991 }
3992
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003993 if (sport == htons(RFC1001_PORT))
3994 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003995
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 return rc;
3997}
3998
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003999static int
4000ip_connect(struct TCP_Server_Info *server)
4001{
Steve French6da97912011-03-13 18:55:55 +00004002 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03004003 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
4004 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
4005
4006 if (server->dstaddr.ss_family == AF_INET6)
4007 sport = &addr6->sin6_port;
4008 else
4009 sport = &addr->sin_port;
4010
4011 if (*sport == 0) {
4012 int rc;
4013
4014 /* try with 445 port at first */
4015 *sport = htons(CIFS_PORT);
4016
4017 rc = generic_ip_connect(server);
4018 if (rc >= 0)
4019 return rc;
4020
4021 /* if it failed, try with 139 port */
4022 *sport = htons(RFC1001_PORT);
4023 }
4024
4025 return generic_ip_connect(server);
4026}
4027
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004028void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04004029 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00004030{
4031 /* if we are reconnecting then should we check to see if
4032 * any requested capabilities changed locally e.g. via
4033 * remount but we can not do much about it here
4034 * if they have (even if we could detect it by the following)
4035 * Perhaps we could add a backpointer to array of sb from tcon
4036 * or if we change to make all sb to same share the same
4037 * sb as NFS - then we only have one backpointer to sb.
4038 * What if we wanted to mount the server share twice once with
4039 * and once without posixacls or posix paths? */
4040 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00004041
Steve Frenchc18c8422007-07-18 23:21:09 +00004042 if (vol_info && vol_info->no_linux_ext) {
4043 tcon->fsUnixInfo.Capability = 0;
4044 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05004045 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004046 return;
4047 } else if (vol_info)
4048 tcon->unix_ext = 1; /* Unix Extensions supported */
4049
4050 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004051 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00004052 return;
4053 }
Steve French50c2f752007-07-13 00:33:32 +00004054
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004055 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00004056 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05004057 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00004058 /* check for reconnect case in which we do not
4059 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004060 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004061 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00004062 originally at mount time */
4063 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
4064 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004065 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
4066 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004067 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00004068 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00004069 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004070 cifs_dbg(VFS, "possible reconnect error\n");
4071 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00004072 }
Steve French8af18972007-02-14 04:42:51 +00004073 }
Steve French50c2f752007-07-13 00:33:32 +00004074
Steve French6848b732011-05-26 18:38:54 +00004075 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004076 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00004077
Steve French8af18972007-02-14 04:42:51 +00004078 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00004079 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00004080 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004081 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004082 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004083 if (cifs_sb)
4084 cifs_sb->mnt_cifs_flags |=
4085 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00004086 }
4087
Steve French75865f8c2007-06-24 18:30:48 +00004088 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00004089 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004090 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004091 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004092 if (cifs_sb)
4093 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00004094 CIFS_MOUNT_POSIX_PATHS;
4095 }
Steve French50c2f752007-07-13 00:33:32 +00004096
Joe Perchesf96637b2013-05-04 22:12:25 -05004097 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00004098#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00004099 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004100 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004101 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004102 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004103 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004104 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004105 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004106 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004107 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004108 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004109 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004110 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004111 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004112 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00004113 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004114 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00004115 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004116 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00004117#endif /* CIFS_DEBUG2 */
4118 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00004119 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004120 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00004121 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05004122 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 +00004123
Steve French8af18972007-02-14 04:42:51 +00004124 }
4125 }
4126}
4127
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004128int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004129 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004130{
Jeff Layton2de970f2010-10-06 19:51:12 -04004131 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
4132
Al Viro2ced6f62011-06-17 09:20:04 -04004133 spin_lock_init(&cifs_sb->tlink_tree_lock);
4134 cifs_sb->tlink_tree = RB_ROOT;
4135
Steve Frenche8506d22019-02-28 21:32:15 -06004136 cifs_sb->bsize = pvolume_info->bsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004137 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004138 * Temporarily set r/wsize for matching superblock. If we end up using
4139 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004140 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004141 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004142 cifs_sb->wsize = pvolume_info->wsize;
4143
Steve French3b795212008-11-13 19:45:32 +00004144 cifs_sb->mnt_uid = pvolume_info->linux_uid;
4145 cifs_sb->mnt_gid = pvolume_info->linux_gid;
4146 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
4147 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05004148 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
4149 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00004150
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304151 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004152 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304153
Aurelien Aptel83930722018-09-20 18:10:25 -07004154 if (pvolume_info->nodfs)
4155 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00004156 if (pvolume_info->noperm)
4157 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4158 if (pvolume_info->setuids)
4159 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05004160 if (pvolume_info->setuidfromacl)
4161 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00004162 if (pvolume_info->server_ino)
4163 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4164 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05004165 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
4166 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00004167 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4168 if (pvolume_info->no_xattr)
4169 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4170 if (pvolume_info->sfu_emul)
4171 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4172 if (pvolume_info->nobrl)
4173 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05004174 if (pvolume_info->nohandlecache)
4175 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00004176 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00004177 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00004178 if (pvolume_info->mand_lock)
4179 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00004180 if (pvolume_info->rwpidforward)
4181 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French412094a2019-06-24 02:01:42 -05004182 if (pvolume_info->mode_ace)
4183 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
Steve French3b795212008-11-13 19:45:32 +00004184 if (pvolume_info->cifs_acl)
4185 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004186 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004187 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004188 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
4189 }
4190 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004191 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004192 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
4193 }
Steve French3b795212008-11-13 19:45:32 +00004194 if (pvolume_info->override_uid)
4195 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
4196 if (pvolume_info->override_gid)
4197 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
4198 if (pvolume_info->dynperm)
4199 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05304200 if (pvolume_info->fsc)
4201 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04004202 if (pvolume_info->multiuser)
4203 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
4204 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05004205 if (pvolume_info->strict_io)
4206 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00004207 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004208 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00004209 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
4210 }
Steve French83bbfa72019-08-27 23:58:54 -05004211 if (pvolume_info->cache_ro) {
4212 cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4213 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
Steve French41e033f2019-08-30 02:12:41 -05004214 } else if (pvolume_info->cache_rw) {
4215 cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4216 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4217 CIFS_MOUNT_RW_CACHE);
Steve French83bbfa72019-08-27 23:58:54 -05004218 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004219 if (pvolume_info->mfsymlinks) {
4220 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05004221 /*
4222 * Our SFU ("Services for Unix" emulation does not allow
4223 * creating symlinks but does allow reading existing SFU
4224 * symlinks (it does allow both creating and reading SFU
4225 * style mknod and FIFOs though). When "mfsymlinks" and
4226 * "sfu" are both enabled at the same time, it allows
4227 * reading both types of symlinks, but will only create
4228 * them with mfsymlinks format. This allows better
4229 * Apple compatibility (probably better for Samba too)
4230 * while still recognizing old Windows style symlinks.
4231 */
4232 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004233 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05004234 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004235 }
Steve French3b795212008-11-13 19:45:32 +00004236
4237 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05004238 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004239
4240 if (pvolume_info->prepath) {
4241 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
4242 if (cifs_sb->prepath == NULL)
4243 return -ENOMEM;
4244 }
4245
4246 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004247}
4248
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004249void
4250cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004251{
Sean Finneyb9468452011-04-11 13:19:32 +00004252 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004253 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02004254 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00004255 kfree(volume_info->domainname);
4256 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004257 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004258}
4259
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004260void
4261cifs_cleanup_volume_info(struct smb_vol *volume_info)
4262{
4263 if (!volume_info)
4264 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004265 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004266 kfree(volume_info);
4267}
4268
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004269/* Release all succeed connections */
4270static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4271 unsigned int xid,
4272 struct TCP_Server_Info *server,
4273 struct cifs_ses *ses, struct cifs_tcon *tcon)
4274{
4275 int rc = 0;
4276
4277 if (tcon)
4278 cifs_put_tcon(tcon);
4279 else if (ses)
4280 cifs_put_smb_ses(ses);
4281 else if (server)
4282 cifs_put_tcp_session(server, 0);
4283 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4284 free_xid(xid);
4285}
4286
4287/* Get connections for tcp, ses and tcon */
4288static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4289 unsigned int *xid,
4290 struct TCP_Server_Info **nserver,
4291 struct cifs_ses **nses, struct cifs_tcon **ntcon)
4292{
4293 int rc = 0;
4294 struct TCP_Server_Info *server;
4295 struct cifs_ses *ses;
4296 struct cifs_tcon *tcon;
4297
4298 *nserver = NULL;
4299 *nses = NULL;
4300 *ntcon = NULL;
4301
4302 *xid = get_xid();
4303
4304 /* get a reference to a tcp session */
4305 server = cifs_get_tcp_session(vol);
4306 if (IS_ERR(server)) {
4307 rc = PTR_ERR(server);
4308 return rc;
4309 }
4310
4311 *nserver = server;
4312
4313 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
4314 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4315 else
4316 server->max_credits = vol->max_credits;
4317
4318 /* get a reference to a SMB session */
4319 ses = cifs_get_smb_ses(server, vol);
4320 if (IS_ERR(ses)) {
4321 rc = PTR_ERR(ses);
4322 return rc;
4323 }
4324
4325 *nses = ses;
4326
4327 if ((vol->persistent == true) && (!(ses->server->capabilities &
4328 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004329 cifs_server_dbg(VFS, "persistent handles not supported by server\n");
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004330 return -EOPNOTSUPP;
4331 }
4332
4333 /* search for existing tcon to this server share */
4334 tcon = cifs_get_tcon(ses, vol);
4335 if (IS_ERR(tcon)) {
4336 rc = PTR_ERR(tcon);
4337 return rc;
4338 }
4339
4340 *ntcon = tcon;
4341
4342 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4343 if (tcon->posix_extensions)
4344 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4345
4346 /* tell server which Unix caps we support */
4347 if (cap_unix(tcon->ses)) {
4348 /*
4349 * reset of caps checks mount to see if unix extensions disabled
4350 * for just this mount.
4351 */
4352 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4353 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4354 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4355 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4356 return -EACCES;
4357 } else
4358 tcon->unix_ext = 0; /* server does not support them */
4359
4360 /* do not care if a following call succeed - informational */
Steve French1981eba2019-08-29 22:33:38 -05004361 if (!tcon->pipe && server->ops->qfs_tcon) {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004362 server->ops->qfs_tcon(*xid, tcon);
Steve French1981eba2019-08-29 22:33:38 -05004363 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4364 if (tcon->fsDevInfo.DeviceCharacteristics &
Steve French52870d52019-10-01 21:25:46 -05004365 cpu_to_le32(FILE_READ_ONLY_DEVICE))
Steve French1981eba2019-08-29 22:33:38 -05004366 cifs_dbg(VFS, "mounted to read only share\n");
Steve French41e033f2019-08-30 02:12:41 -05004367 else if ((cifs_sb->mnt_cifs_flags &
4368 CIFS_MOUNT_RW_CACHE) == 0)
Steve French1981eba2019-08-29 22:33:38 -05004369 cifs_dbg(VFS, "read only mount of RW share\n");
Steve French41e033f2019-08-30 02:12:41 -05004370 /* no need to log a RW mount of a typical RW share */
Steve French1981eba2019-08-29 22:33:38 -05004371 }
4372 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004373
4374 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4375 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4376
4377 return 0;
4378}
4379
4380static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4381 struct cifs_tcon *tcon)
4382{
4383 struct tcon_link *tlink;
4384
4385 /* hang the tcon off of the superblock */
4386 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4387 if (tlink == NULL)
4388 return -ENOMEM;
4389
4390 tlink->tl_uid = ses->linux_uid;
4391 tlink->tl_tcon = tcon;
4392 tlink->tl_time = jiffies;
4393 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4394 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4395
4396 cifs_sb->master_tlink = tlink;
4397 spin_lock(&cifs_sb->tlink_tree_lock);
4398 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4399 spin_unlock(&cifs_sb->tlink_tree_lock);
4400
4401 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4402 TLINK_IDLE_EXPIRE);
4403 return 0;
4404}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004405
Steve French2d6d5892009-04-09 00:36:44 +00004406#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004407/*
4408 * cifs_build_path_to_root returns full path to root when we do not have an
4409 * exiting connection (tcon)
4410 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004411static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004412build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004413 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004414{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004415 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004416 unsigned int pplen = useppath && vol->prepath ?
4417 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004418 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004419
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004420 if (unc_len > MAX_TREE_SIZE)
4421 return ERR_PTR(-EINVAL);
4422
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004423 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004424 if (full_path == NULL)
4425 return ERR_PTR(-ENOMEM);
4426
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004427 memcpy(full_path, vol->UNC, unc_len);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004428 pos = full_path + unc_len;
4429
4430 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004431 *pos = CIFS_DIR_SEP(cifs_sb);
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004432 memcpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004433 pos += pplen;
4434 }
4435
4436 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004437 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004438 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004439 return full_path;
4440}
Sean Finneydd613942011-04-11 13:19:30 +00004441
Paulo Alcantara1c780222018-11-14 16:24:03 -02004442/**
4443 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4444 *
Sean Finneydd613942011-04-11 13:19:30 +00004445 *
Sean Finney046462a2011-04-11 13:19:33 +00004446 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4447 * to a string containing updated options for the submount. Otherwise it
4448 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004449 *
4450 * Returns the rc from get_dfs_path to the caller, which can be used to
4451 * determine whether there were referrals.
4452 */
4453static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004454expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004455 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00004456 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00004457{
4458 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004459 struct dfs_info3_param referral = {0};
Sean Finneydd613942011-04-11 13:19:30 +00004460 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4461
Aurelien Aptel83930722018-09-20 18:10:25 -07004462 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4463 return -EREMOTE;
4464
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004465 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004466 if (IS_ERR(full_path))
4467 return PTR_ERR(full_path);
4468
4469 /* For DFS paths, skip the first '\' of the UNC */
4470 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4471
Paulo Alcantara1c780222018-11-14 16:24:03 -02004472 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4473 ref_path, &referral, NULL);
4474 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004475 char *fake_devname = NULL;
4476
4477 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004478 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004479 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004480 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004481
Sean Finneydd613942011-04-11 13:19:30 +00004482 if (IS_ERR(mdata)) {
4483 rc = PTR_ERR(mdata);
4484 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004485 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004486 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004487 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004488 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004489 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004490 kfree(fake_devname);
4491 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004492 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004493 }
4494 kfree(full_path);
4495 return rc;
4496}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004497
4498static inline int get_next_dfs_tgt(const char *path,
4499 struct dfs_cache_tgt_list *tgt_list,
4500 struct dfs_cache_tgt_iterator **tgt_it)
4501{
4502 if (!*tgt_it)
4503 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4504 else
4505 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4506 return !*tgt_it ? -EHOSTDOWN : 0;
4507}
4508
4509static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4510 struct smb_vol *fake_vol, struct smb_vol *vol)
4511{
4512 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4513 int len = strlen(tgt) + 2;
4514 char *new_unc;
4515
4516 new_unc = kmalloc(len, GFP_KERNEL);
4517 if (!new_unc)
4518 return -ENOMEM;
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +10004519 scnprintf(new_unc, len, "\\%s", tgt);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004520
4521 kfree(vol->UNC);
4522 vol->UNC = new_unc;
4523
4524 if (fake_vol->prepath) {
4525 kfree(vol->prepath);
4526 vol->prepath = fake_vol->prepath;
4527 fake_vol->prepath = NULL;
4528 }
4529 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4530
4531 return 0;
4532}
4533
4534static int setup_dfs_tgt_conn(const char *path,
4535 const struct dfs_cache_tgt_iterator *tgt_it,
4536 struct cifs_sb_info *cifs_sb,
4537 struct smb_vol *vol,
4538 unsigned int *xid,
4539 struct TCP_Server_Info **server,
4540 struct cifs_ses **ses,
4541 struct cifs_tcon **tcon)
4542{
4543 int rc;
4544 struct dfs_info3_param ref = {0};
4545 char *mdata = NULL, *fake_devname = NULL;
Steve Frenchd0959b02019-10-05 10:53:58 -05004546 struct smb_vol fake_vol = {NULL};
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004547
4548 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4549
4550 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4551 if (rc)
4552 return rc;
4553
4554 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4555 &fake_devname);
4556 free_dfs_info_param(&ref);
4557
4558 if (IS_ERR(mdata)) {
4559 rc = PTR_ERR(mdata);
4560 mdata = NULL;
4561 } else {
4562 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4563 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4564 false);
4565 }
4566 kfree(mdata);
4567 kfree(fake_devname);
4568
4569 if (!rc) {
4570 /*
4571 * We use a 'fake_vol' here because we need pass it down to the
4572 * mount_{get,put} functions to test connection against new DFS
4573 * targets.
4574 */
4575 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4576 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4577 tcon);
4578 if (!rc) {
4579 /*
4580 * We were able to connect to new target server.
4581 * Update current volume info with new target server.
4582 */
4583 rc = update_vol_info(tgt_it, &fake_vol, vol);
4584 }
4585 }
4586 cifs_cleanup_volume_info_contents(&fake_vol);
4587 return rc;
4588}
4589
4590static int mount_do_dfs_failover(const char *path,
4591 struct cifs_sb_info *cifs_sb,
4592 struct smb_vol *vol,
4593 struct cifs_ses *root_ses,
4594 unsigned int *xid,
4595 struct TCP_Server_Info **server,
4596 struct cifs_ses **ses,
4597 struct cifs_tcon **tcon)
4598{
4599 int rc;
4600 struct dfs_cache_tgt_list tgt_list;
4601 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4602
4603 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4604 return -EOPNOTSUPP;
4605
4606 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4607 if (rc)
4608 return rc;
4609
4610 for (;;) {
4611 /* Get next DFS target server - if any */
4612 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4613 if (rc)
4614 break;
4615 /* Connect to next DFS target */
4616 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4617 ses, tcon);
4618 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4619 break;
4620 }
4621 if (!rc) {
4622 /*
4623 * Update DFS target hint in DFS referral cache with the target
4624 * server we successfully reconnected to.
4625 */
4626 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4627 cifs_sb->local_nls,
4628 cifs_remap(cifs_sb), path,
4629 tgt_it);
4630 }
4631 dfs_cache_free_tgts(&tgt_list);
4632 return rc;
4633}
Steve French2d6d5892009-04-09 00:36:44 +00004634#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004635
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004636int
Jeff Layton04db79b2011-07-06 08:10:38 -04004637cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004638 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004639{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004640 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004641
Steve Frenchc7c137b2018-06-06 17:59:29 -05004642 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004643 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644
Jeff Layton7586b762008-12-01 18:41:49 -05004645 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004646 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004647 kfree(volume_info->username);
4648 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004649 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004651 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004653 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004654 /* In userspace mount helper we can get user name from alternate
4655 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004656 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657 }
4658
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004660 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004661 /* load_nls_default cannot return null */
4662 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004664 volume_info->local_nls = load_nls(volume_info->iocharset);
4665 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004666 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004667 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004668 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669 }
4670 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004671
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004672 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004673}
4674
4675struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004676cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004677{
4678 int rc;
4679 struct smb_vol *volume_info;
4680
Jeff Layton6ee95422012-11-26 11:09:57 -05004681 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004682 if (!volume_info)
4683 return ERR_PTR(-ENOMEM);
4684
Steve Frenchc7c137b2018-06-06 17:59:29 -05004685 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004686 if (rc) {
4687 cifs_cleanup_volume_info(volume_info);
4688 volume_info = ERR_PTR(rc);
4689 }
4690
4691 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004692}
4693
Aurelien Aptela6b50582016-05-25 19:59:09 +02004694static int
4695cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4696 unsigned int xid,
4697 struct cifs_tcon *tcon,
4698 struct cifs_sb_info *cifs_sb,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004699 char *full_path,
4700 int added_treename)
Aurelien Aptela6b50582016-05-25 19:59:09 +02004701{
4702 int rc;
4703 char *s;
4704 char sep, tmp;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004705 int skip = added_treename ? 1 : 0;
Aurelien Aptela6b50582016-05-25 19:59:09 +02004706
4707 sep = CIFS_DIR_SEP(cifs_sb);
4708 s = full_path;
4709
4710 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4711 while (rc == 0) {
4712 /* skip separators */
4713 while (*s == sep)
4714 s++;
4715 if (!*s)
4716 break;
4717 /* next separator */
4718 while (*s && *s != sep)
4719 s++;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004720 /*
4721 * if the treename is added, we then have to skip the first
4722 * part within the separators
4723 */
4724 if (skip) {
4725 skip = 0;
4726 continue;
4727 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004728 /*
4729 * temporarily null-terminate the path at the end of
4730 * the current component
4731 */
4732 tmp = *s;
4733 *s = 0;
4734 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4735 full_path);
4736 *s = tmp;
4737 }
4738 return rc;
4739}
4740
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004741/*
4742 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4743 * otherwise 0.
4744 */
4745static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4746 const unsigned int xid,
4747 struct TCP_Server_Info *server,
4748 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004749{
Jeff Layton1daaae82012-03-21 06:30:40 -04004750 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004751 char *full_path;
4752
4753 if (!server->ops->is_path_accessible)
4754 return -EOPNOTSUPP;
4755
4756 /*
4757 * cifs_build_path_to_root works only when we have a valid tcon
4758 */
4759 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4760 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4761 if (full_path == NULL)
4762 return -ENOMEM;
4763
4764 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4765
4766 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4767 full_path);
4768 if (rc != 0 && rc != -EREMOTE) {
4769 kfree(full_path);
4770 return rc;
4771 }
4772
4773 if (rc != -EREMOTE) {
4774 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004775 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004776 if (rc != 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004777 cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004778 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4779 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4780 rc = 0;
4781 }
4782 }
4783
4784 kfree(full_path);
4785 return rc;
4786}
4787
4788#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004789static inline void set_root_tcon(struct cifs_sb_info *cifs_sb,
4790 struct cifs_tcon *tcon,
4791 struct cifs_tcon **root)
4792{
4793 spin_lock(&cifs_tcp_ses_lock);
4794 tcon->tc_count++;
4795 tcon->remap = cifs_remap(cifs_sb);
4796 spin_unlock(&cifs_tcp_ses_lock);
4797 *root = tcon;
4798}
4799
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004800int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4801{
4802 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004803 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004804 struct cifs_ses *ses;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004805 struct cifs_tcon *root_tcon = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004806 struct cifs_tcon *tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004807 struct TCP_Server_Info *server;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004808 char *root_path = NULL, *full_path = NULL;
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004809 char *old_mountdata, *origin_mountdata = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004810 int count;
Al Virodd854462011-06-17 08:24:42 -04004811
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004812 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4813 if (!rc && tcon) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004814 /* If not a standalone DFS root, then check if path is remote */
4815 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4816 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4817 NULL);
4818 if (rc) {
4819 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4820 if (!rc)
4821 goto out;
4822 if (rc != -EREMOTE)
4823 goto error;
4824 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004825 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004826 /*
4827 * If first DFS target server went offline and we failed to connect it,
4828 * server and ses pointers are NULL at this point, though we still have
4829 * chance to get a cached DFS referral in expand_dfs_referral() and
4830 * retry next target available in it.
4831 *
4832 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4833 * performed against DFS path and *no* requests will be sent to server
4834 * for any new DFS referrals. Hence it's safe to skip checking whether
4835 * server or ses ptr is NULL.
4836 */
4837 if (rc == -EACCES || rc == -EOPNOTSUPP)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004838 goto error;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004839
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004840 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4841 if (IS_ERR(root_path)) {
4842 rc = PTR_ERR(root_path);
4843 root_path = NULL;
4844 goto error;
4845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004846
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004847 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4848 if (IS_ERR(full_path)) {
4849 rc = PTR_ERR(full_path);
4850 full_path = NULL;
4851 goto error;
4852 }
Sean Finneyc1508ca2011-04-11 13:19:31 +00004853 /*
4854 * Perform an unconditional check for whether there are DFS
4855 * referrals for this path without prefix, to provide support
4856 * for DFS referrals from w2k8 servers which don't seem to respond
4857 * with PATH_NOT_COVERED to requests that include the prefix.
4858 * Chase the referral if found, otherwise continue normally.
4859 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004860 old_mountdata = cifs_sb->mountdata;
4861 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004862
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004863 if (cifs_sb->mountdata == NULL) {
4864 rc = -ENOENT;
4865 goto error;
4866 }
4867
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004868 /* Save DFS root volume information for DFS refresh worker */
4869 origin_mountdata = kstrndup(cifs_sb->mountdata,
4870 strlen(cifs_sb->mountdata), GFP_KERNEL);
4871 if (!origin_mountdata) {
4872 rc = -ENOMEM;
4873 goto error;
4874 }
4875
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004876 if (cifs_sb->mountdata != old_mountdata) {
4877 /* If we were redirected, reconnect to new target server */
4878 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4879 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4880 }
4881 if (rc) {
4882 if (rc == -EACCES || rc == -EOPNOTSUPP)
4883 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004884 /* Perform DFS failover to any other DFS targets */
4885 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4886 &xid, &server, &ses, &tcon);
4887 if (rc)
4888 goto error;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004889 }
4890
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004891 kfree(root_path);
4892 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4893 if (IS_ERR(root_path)) {
4894 rc = PTR_ERR(root_path);
4895 root_path = NULL;
4896 goto error;
4897 }
4898 /* Cache out resolved root server */
4899 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4900 root_path + 1, NULL, NULL);
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004901 kfree(root_path);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004902 root_path = NULL;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004903
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004904 set_root_tcon(cifs_sb, tcon, &root_tcon);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004905
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004906 for (count = 1; ;) {
4907 if (!rc && tcon) {
4908 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4909 if (!rc || rc != -EREMOTE)
4910 break;
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004911 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004912 /*
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004913 * BB: when we implement proper loop detection,
4914 * we will remove this check. But now we need it
4915 * to prevent an indefinite loop if 'DFS tree' is
4916 * misconfigured (i.e. has loops).
Steve French6d3ea7e2012-11-28 22:34:41 -06004917 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004918 if (count++ > MAX_NESTED_LINKS) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004919 rc = -ELOOP;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004920 break;
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004921 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004922
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004923 kfree(full_path);
4924 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4925 if (IS_ERR(full_path)) {
4926 rc = PTR_ERR(full_path);
4927 full_path = NULL;
4928 break;
4929 }
4930
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004931 old_mountdata = cifs_sb->mountdata;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004932 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004933 true);
4934 if (rc)
4935 break;
Jeff Layton7b91e262009-07-23 15:22:30 -04004936
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004937 if (cifs_sb->mountdata != old_mountdata) {
4938 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4939 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4940 &tcon);
Paulo Alcantara (SUSE)5bb30a42019-11-22 12:30:56 -03004941 /*
4942 * Ensure that DFS referrals go through new root server.
4943 */
4944 if (!rc && tcon &&
4945 (tcon->share_flags & (SHI1005_FLAGS_DFS |
4946 SHI1005_FLAGS_DFS_ROOT))) {
4947 cifs_put_tcon(root_tcon);
4948 set_root_tcon(cifs_sb, tcon, &root_tcon);
4949 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004950 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004951 if (rc) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004952 if (rc == -EACCES || rc == -EOPNOTSUPP)
4953 break;
4954 /* Perform DFS failover to any other DFS targets */
4955 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4956 root_tcon->ses, &xid,
4957 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004958 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4959 !ses)
4960 goto error;
4961 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004962 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004963 cifs_put_tcon(root_tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004964
Jeff Layton9d002df2010-10-06 19:51:11 -04004965 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004966 goto error;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004967
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004968 spin_lock(&cifs_tcp_ses_lock);
4969 if (!tcon->dfs_path) {
4970 /* Save full path in new tcon to do failover when reconnecting tcons */
4971 tcon->dfs_path = full_path;
4972 full_path = NULL;
4973 tcon->remap = cifs_remap(cifs_sb);
4974 }
4975 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
YueHaibing2f0a6172018-12-18 01:34:39 +00004976 strlen(tcon->dfs_path),
4977 GFP_ATOMIC);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004978 if (!cifs_sb->origin_fullpath) {
4979 spin_unlock(&cifs_tcp_ses_lock);
4980 rc = -ENOMEM;
4981 goto error;
4982 }
4983 spin_unlock(&cifs_tcp_ses_lock);
4984
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004985 rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath);
Paulo Alcantarae511d312018-11-14 17:16:44 -02004986 if (rc) {
4987 kfree(cifs_sb->origin_fullpath);
4988 goto error;
4989 }
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004990 /*
4991 * After reconnecting to a different server, unique ids won't
4992 * match anymore, so we disable serverino. This prevents
4993 * dentry revalidation to think the dentry are stale (ESTALE).
4994 */
4995 cifs_autodisable_serverino(cifs_sb);
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004996out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004997 free_xid(xid);
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02004998 cifs_try_adding_channels(ses);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004999 return mount_setup_tlink(cifs_sb, ses, tcon);
5000
5001error:
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02005002 kfree(full_path);
5003 kfree(root_path);
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03005004 kfree(origin_mountdata);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02005005 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006 return rc;
5007}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02005008#else
5009int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
5010{
5011 int rc = 0;
5012 unsigned int xid;
5013 struct cifs_ses *ses;
5014 struct cifs_tcon *tcon;
5015 struct TCP_Server_Info *server;
5016
5017 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
5018 if (rc)
5019 goto error;
5020
5021 if (tcon) {
5022 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
5023 if (rc == -EREMOTE)
5024 rc = -EOPNOTSUPP;
5025 if (rc)
5026 goto error;
5027 }
5028
5029 free_xid(xid);
5030
5031 return mount_setup_tlink(cifs_sb, ses, tcon);
5032
5033error:
5034 mount_put_conns(cifs_sb, xid, server, ses, tcon);
5035 return rc;
5036}
5037#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038
Jeff Layton8d1bca32011-06-11 21:17:10 -04005039/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01005040 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04005041 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04005043CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00005044 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045 const struct nls_table *nls_codepage)
5046{
5047 struct smb_hdr *smb_buffer;
5048 struct smb_hdr *smb_buffer_response;
5049 TCONX_REQ *pSMB;
5050 TCONX_RSP *pSMBr;
5051 unsigned char *bcc_ptr;
5052 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05005053 int length;
5054 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055
5056 if (ses == NULL)
5057 return -EIO;
5058
5059 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00005060 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00005062
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063 smb_buffer_response = smb_buffer;
5064
5065 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
5066 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07005067
Pavel Shilovsky88257362012-05-23 14:01:59 +04005068 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069 smb_buffer->Uid = ses->Suid;
5070 pSMB = (TCONX_REQ *) smb_buffer;
5071 pSMBr = (TCONX_RSP *) smb_buffer_response;
5072
5073 pSMB->AndXCommand = 0xFF;
5074 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01005076 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08005077 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00005078 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08005079 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00005080 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08005081 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005082 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08005083 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
5084 specified as required (when that support is added to
5085 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00005086 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08005087 by Samba (not sure whether other servers allow
5088 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00005089#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04005090 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05005091 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05005092 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00005093 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05005094 SECMODE_PW_ENCRYPT ? true : false,
5095 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00005096 else
5097#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06005098 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05005099 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05005100 if (rc) {
5101 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
5102 __func__, rc);
5103 cifs_buf_release(smb_buffer);
5104 return rc;
5105 }
Steve Frencheeac8042006-01-13 21:34:58 -08005106
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005107 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005108 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00005109 /* must align unicode strings */
5110 *bcc_ptr = 0; /* null byte password */
5111 bcc_ptr++;
5112 }
Steve Frencheeac8042006-01-13 21:34:58 -08005113 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114
Jeff Layton38d77c52013-05-26 07:01:00 -04005115 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
5117
5118 if (ses->capabilities & CAP_STATUS32) {
5119 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
5120 }
5121 if (ses->capabilities & CAP_DFS) {
5122 smb_buffer->Flags2 |= SMBFLG2_DFS;
5123 }
5124 if (ses->capabilities & CAP_UNICODE) {
5125 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
5126 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06005127 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00005128 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00005129 (/* server len*/ + 256 /* share len */), nls_codepage);
5130 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005131 bcc_ptr += 2; /* skip trailing null */
5132 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133 strcpy(bcc_ptr, tree);
5134 bcc_ptr += strlen(tree) + 1;
5135 }
5136 strcpy(bcc_ptr, "?????");
5137 bcc_ptr += strlen("?????");
5138 bcc_ptr += 1;
5139 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00005140 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
5141 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142 pSMB->ByteCount = cpu_to_le16(count);
5143
Steve French133672e2007-11-13 22:41:37 +00005144 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05005145 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005146
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01005148 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00005149 bool is_unicode;
5150
Linus Torvalds1da177e2005-04-16 15:20:36 -07005151 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00005152 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153 tcon->tid = smb_buffer_response->Tid;
5154 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05005155 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005156 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00005157 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
5158 is_unicode = true;
5159 else
5160 is_unicode = false;
5161
Jeff Laytoncc20c032009-04-30 07:16:21 -04005162
Steve French50c2f752007-07-13 00:33:32 +00005163 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00005164 if (length == 3) {
5165 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
5166 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05005167 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01005168 tcon->ipc = true;
5169 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00005170 }
5171 } else if (length == 2) {
5172 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
5173 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05005174 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00005175 }
5176 }
Steve French50c2f752007-07-13 00:33:32 +00005177 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04005178 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05005179 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04005180
5181 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04005182 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06005183 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00005184 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04005185 nls_codepage);
5186
Joe Perchesf96637b2013-05-04 22:12:25 -05005187 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005188
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005189 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00005190 (smb_buffer_response->WordCount == 7))
5191 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00005192 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
5193 else
5194 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05005195 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196 }
5197
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00005198 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005199 return rc;
5200}
5201
Al Viro2e32cf52013-10-03 12:53:37 -04005202static void delayed_free(struct rcu_head *p)
5203{
5204 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
5205 unload_nls(sbi->local_nls);
5206 kfree(sbi);
5207}
5208
Al Viro2a9b9952011-06-17 09:27:16 -04005209void
5210cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211{
Jeff Laytonb647c352010-10-28 11:16:44 -04005212 struct rb_root *root = &cifs_sb->tlink_tree;
5213 struct rb_node *node;
5214 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215
Jeff Layton2de970f2010-10-06 19:51:12 -04005216 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
5217
Jeff Laytonb647c352010-10-28 11:16:44 -04005218 spin_lock(&cifs_sb->tlink_tree_lock);
5219 while ((node = rb_first(root))) {
5220 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5221 cifs_get_tlink(tlink);
5222 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5223 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00005224
Jeff Laytonb647c352010-10-28 11:16:44 -04005225 spin_unlock(&cifs_sb->tlink_tree_lock);
5226 cifs_put_tlink(tlink);
5227 spin_lock(&cifs_sb->tlink_tree_lock);
5228 }
5229 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005230
Al Virod757d712011-06-17 09:42:43 -04005231 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02005232 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005233#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02005234 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005235 kfree(cifs_sb->origin_fullpath);
5236#endif
Al Viro2e32cf52013-10-03 12:53:37 -04005237 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00005238}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005240int
5241cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005242{
5243 int rc = 0;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005244 struct TCP_Server_Info *server = cifs_ses_server(ses);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005246 if (!server->ops->need_neg || !server->ops->negotiate)
5247 return -ENOSYS;
5248
Jeff Layton198b5682010-04-24 07:57:48 -04005249 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005250 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04005251 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005253 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005254 if (rc == 0) {
5255 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04005256 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04005257 server->tcpStatus = CifsGood;
5258 else
5259 rc = -EHOSTDOWN;
5260 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005261 }
Steve French26b994f2008-08-06 05:11:33 +00005262
Jeff Layton198b5682010-04-24 07:57:48 -04005263 return rc;
5264}
Steve French26b994f2008-08-06 05:11:33 +00005265
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005266int
5267cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
5268 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04005269{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005270 int rc = -ENOSYS;
Aurelien Aptelf6a6bf72019-09-20 06:22:14 +02005271 struct TCP_Server_Info *server = cifs_ses_server(ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005272
Aurelien Apteld70e9fa2019-09-20 06:31:10 +02005273 if (!ses->binding) {
5274 ses->capabilities = server->capabilities;
5275 if (linuxExtEnabled == 0)
5276 ses->capabilities &= (~server->vals->cap_unix);
5277
5278 if (ses->auth_key.response) {
5279 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
5280 ses->auth_key.response);
5281 kfree(ses->auth_key.response);
5282 ses->auth_key.response = NULL;
5283 ses->auth_key.len = 0;
5284 }
5285 }
Steve French20418ac2009-04-30 16:13:32 +00005286
Joe Perchesf96637b2013-05-04 22:12:25 -05005287 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00005288 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04005289
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005290 if (server->ops->sess_setup)
5291 rc = server->ops->sess_setup(xid, ses, nls_info);
5292
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05005293 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10005294 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05005295
Linus Torvalds1da177e2005-04-16 15:20:36 -07005296 return rc;
5297}
5298
Jeff Layton8a8798a2012-01-17 16:09:15 -05005299static int
5300cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
5301{
Jeff Layton3f618222013-06-12 19:52:14 -05005302 vol->sectype = ses->sectype;
5303
5304 /* krb5 is special, since we don't need username or pw */
5305 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05005306 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05005307
5308 return cifs_set_cifscreds(vol, ses);
5309}
5310
Steve French96daf2b2011-05-27 04:34:02 +00005311static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005312cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04005313{
Jeff Layton8a8798a2012-01-17 16:09:15 -05005314 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00005315 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
5316 struct cifs_ses *ses;
5317 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04005318 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04005319
5320 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03005321 if (vol_info == NULL)
5322 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04005323
Jeff Layton9d002df2010-10-06 19:51:11 -04005324 vol_info->local_nls = cifs_sb->local_nls;
5325 vol_info->linux_uid = fsuid;
5326 vol_info->cred_uid = fsuid;
5327 vol_info->UNC = master_tcon->treeName;
5328 vol_info->retry = master_tcon->retry;
5329 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05005330 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04005331 vol_info->local_lease = master_tcon->local_lease;
5332 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04005333 vol_info->sectype = master_tcon->ses->sectype;
5334 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04005335
Jeff Layton8a8798a2012-01-17 16:09:15 -05005336 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
5337 if (rc) {
5338 tcon = ERR_PTR(rc);
5339 goto out;
5340 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005341
5342 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305343 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005344 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305345 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005346
5347 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
5348 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00005349 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07005350 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04005351 goto out;
5352 }
5353
5354 tcon = cifs_get_tcon(ses, vol_info);
5355 if (IS_ERR(tcon)) {
5356 cifs_put_smb_ses(ses);
5357 goto out;
5358 }
5359
Steve Frenchce558b02018-05-31 19:16:54 -05005360 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
5361 if (tcon->posix_extensions)
5362 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05005363
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005364 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04005365 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05005366
Jeff Layton9d002df2010-10-06 19:51:11 -04005367out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05005368 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01005369 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005370 kfree(vol_info);
5371
5372 return tcon;
5373}
5374
Steve French96daf2b2011-05-27 04:34:02 +00005375struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005376cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5377{
5378 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5379}
5380
Jeff Laytonb647c352010-10-28 11:16:44 -04005381/* find and return a tlink with given uid */
5382static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005383tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005384{
5385 struct rb_node *node = root->rb_node;
5386 struct tcon_link *tlink;
5387
5388 while (node) {
5389 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5390
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005391 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005392 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005393 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005394 node = node->rb_right;
5395 else
5396 return tlink;
5397 }
5398 return NULL;
5399}
5400
5401/* insert a tcon_link into the tree */
5402static void
5403tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5404{
5405 struct rb_node **new = &(root->rb_node), *parent = NULL;
5406 struct tcon_link *tlink;
5407
5408 while (*new) {
5409 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5410 parent = *new;
5411
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005412 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005413 new = &((*new)->rb_left);
5414 else
5415 new = &((*new)->rb_right);
5416 }
5417
5418 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5419 rb_insert_color(&new_tlink->tl_rbnode, root);
5420}
5421
Jeff Layton9d002df2010-10-06 19:51:11 -04005422/*
5423 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5424 * current task.
5425 *
5426 * If the superblock doesn't refer to a multiuser mount, then just return
5427 * the master tcon for the mount.
5428 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305429 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005430 * exists, then check to see if it's pending construction. If it is then wait
5431 * for construction to complete. Once it's no longer pending, check to see if
5432 * it failed and either return an error or retry construction, depending on
5433 * the timeout.
5434 *
5435 * If one doesn't exist then insert a new tcon_link struct into the tree and
5436 * try to construct a new one.
5437 */
5438struct tcon_link *
5439cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5440{
5441 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005442 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005443 struct tcon_link *tlink, *newtlink;
5444
5445 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5446 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5447
5448 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005449 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005450 if (tlink)
5451 cifs_get_tlink(tlink);
5452 spin_unlock(&cifs_sb->tlink_tree_lock);
5453
5454 if (tlink == NULL) {
5455 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5456 if (newtlink == NULL)
5457 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005458 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005459 newtlink->tl_tcon = ERR_PTR(-EACCES);
5460 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5461 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5462 cifs_get_tlink(newtlink);
5463
Jeff Layton9d002df2010-10-06 19:51:11 -04005464 spin_lock(&cifs_sb->tlink_tree_lock);
5465 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005466 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005467 if (tlink) {
5468 cifs_get_tlink(tlink);
5469 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005470 kfree(newtlink);
5471 goto wait_for_construction;
5472 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005473 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005474 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5475 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005476 } else {
5477wait_for_construction:
5478 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005479 TASK_INTERRUPTIBLE);
5480 if (ret) {
5481 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005482 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005483 }
5484
5485 /* if it's good, return it */
5486 if (!IS_ERR(tlink->tl_tcon))
5487 return tlink;
5488
5489 /* return error if we tried this already recently */
5490 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5491 cifs_put_tlink(tlink);
5492 return ERR_PTR(-EACCES);
5493 }
5494
5495 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5496 goto wait_for_construction;
5497 }
5498
5499 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5500 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5501 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5502
5503 if (IS_ERR(tlink->tl_tcon)) {
5504 cifs_put_tlink(tlink);
5505 return ERR_PTR(-EACCES);
5506 }
5507
5508 return tlink;
5509}
Jeff Layton2de970f2010-10-06 19:51:12 -04005510
5511/*
5512 * periodic workqueue job that scans tcon_tree for a superblock and closes
5513 * out tcons.
5514 */
5515static void
5516cifs_prune_tlinks(struct work_struct *work)
5517{
5518 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5519 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005520 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005521 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005522 struct rb_node *tmp;
5523 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005524
Jeff Laytonb647c352010-10-28 11:16:44 -04005525 /*
5526 * Because we drop the spinlock in the loop in order to put the tlink
5527 * it's not guarded against removal of links from the tree. The only
5528 * places that remove entries from the tree are this function and
5529 * umounts. Because this function is non-reentrant and is canceled
5530 * before umount can proceed, this is safe.
5531 */
5532 spin_lock(&cifs_sb->tlink_tree_lock);
5533 node = rb_first(root);
5534 while (node != NULL) {
5535 tmp = node;
5536 node = rb_next(tmp);
5537 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5538
5539 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5540 atomic_read(&tlink->tl_count) != 0 ||
5541 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5542 continue;
5543
5544 cifs_get_tlink(tlink);
5545 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5546 rb_erase(tmp, root);
5547
Jeff Layton2de970f2010-10-06 19:51:12 -04005548 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005549 cifs_put_tlink(tlink);
5550 spin_lock(&cifs_sb->tlink_tree_lock);
5551 }
5552 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005553
Jeff Laytonda472fc2012-03-23 14:40:53 -04005554 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005555 TLINK_IDLE_EXPIRE);
5556}