blob: a59dcda07534353f62301a8548a6de591a7c51b3 [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"
Paulo Alcantarac0be6242018-11-20 15:16:36 -020053#include "dns_resolve.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include "ntlmssp.h"
55#include "nterr.h"
56#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053057#include "fscache.h"
Pavel Shilovsky53e0e112016-11-04 11:50:31 -070058#include "smb2proto.h"
Long Li2f894642017-11-22 17:38:34 -070059#include "smbdirect.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Linus Torvalds1da177e2005-04-16 15:20:36 -070061extern mempool_t *cifs_req_poolp;
Steve Frenchf92a7202018-05-24 04:11:07 -050062extern bool disable_legacy_dialects;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Jeff Layton2de970f2010-10-06 19:51:12 -040064/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040065#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040066#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040067
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040068enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040069 /* Mount options that take no arguments */
70 Opt_user_xattr, Opt_nouser_xattr,
71 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040072 Opt_forcegid, Opt_noforcegid,
Steve French2e96c932019-09-11 21:46:20 -050073 Opt_noblocksend, Opt_noautotune, Opt_nolease,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040074 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
Steve French2baa2682014-09-27 02:19:01 -050075 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040076 Opt_mapchars, Opt_nomapchars, Opt_sfu,
77 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
Steve Frenchb3266142018-05-20 23:41:10 -050078 Opt_noposixpaths, Opt_nounix, Opt_unix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040079 Opt_nocase,
80 Opt_brl, Opt_nobrl,
Steve French3d4ef9a2018-04-25 22:19:09 -050081 Opt_handlecache, Opt_nohandlecache,
Steve French95932652016-09-23 01:36:34 -050082 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040083 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
84 Opt_nohard, Opt_nosoft,
85 Opt_nointr, Opt_intr,
86 Opt_nostrictsync, Opt_strictsync,
87 Opt_serverino, Opt_noserverino,
88 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
89 Opt_acl, Opt_noacl, Opt_locallease,
Jeff Layton1b359202012-09-19 15:20:27 -070090 Opt_sign, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040091 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -040092 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -050093 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -060094 Opt_resilient, Opt_noresilient,
Long Li8339dd32017-11-07 01:54:55 -070095 Opt_domainauto, Opt_rdma,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040096
97 /* Mount options which take numeric value */
98 Opt_backupuid, Opt_backupgid, Opt_uid,
99 Opt_cruid, Opt_gid, Opt_file_mode,
100 Opt_dirmode, Opt_port,
101 Opt_rsize, Opt_wsize, Opt_actimeo,
Steve French141891f2016-09-23 00:44:16 -0500102 Opt_echo_interval, Opt_max_credits,
Steve French8b217fe2016-11-11 22:36:20 -0600103 Opt_snapshot,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400104
105 /* Mount options which take string value */
106 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400107 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400108 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400109 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400110
111 /* Mount options to be ignored */
112 Opt_ignore,
113
114 /* Options which could be blank */
115 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100116 Opt_blank_user,
117 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400118
119 Opt_err
120};
121
122static const match_table_t cifs_mount_option_tokens = {
123
124 { Opt_user_xattr, "user_xattr" },
125 { Opt_nouser_xattr, "nouser_xattr" },
126 { Opt_forceuid, "forceuid" },
127 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400128 { Opt_forcegid, "forcegid" },
129 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400130 { Opt_noblocksend, "noblocksend" },
131 { Opt_noautotune, "noautotune" },
Steve French2e96c932019-09-11 21:46:20 -0500132 { Opt_nolease, "nolease" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400133 { Opt_hard, "hard" },
134 { Opt_soft, "soft" },
135 { Opt_perm, "perm" },
136 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500137 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400138 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500139 { Opt_mapposix, "mapposix" }, /* SFM style */
140 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400141 { Opt_sfu, "sfu" },
142 { Opt_nosfu, "nosfu" },
143 { Opt_nodfs, "nodfs" },
144 { Opt_posixpaths, "posixpaths" },
145 { Opt_noposixpaths, "noposixpaths" },
146 { Opt_nounix, "nounix" },
147 { Opt_nounix, "nolinux" },
Steve Frenchb3266142018-05-20 23:41:10 -0500148 { Opt_nounix, "noposix" },
149 { Opt_unix, "unix" },
150 { Opt_unix, "linux" },
151 { Opt_unix, "posix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400152 { Opt_nocase, "nocase" },
153 { Opt_nocase, "ignorecase" },
154 { Opt_brl, "brl" },
155 { Opt_nobrl, "nobrl" },
Steve French3d4ef9a2018-04-25 22:19:09 -0500156 { Opt_handlecache, "handlecache" },
157 { Opt_nohandlecache, "nohandlecache" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400158 { Opt_nobrl, "nolock" },
159 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400160 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400161 { Opt_setuids, "setuids" },
162 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500163 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400164 { Opt_dynperm, "dynperm" },
165 { Opt_nodynperm, "nodynperm" },
166 { Opt_nohard, "nohard" },
167 { Opt_nosoft, "nosoft" },
168 { Opt_nointr, "nointr" },
169 { Opt_intr, "intr" },
170 { Opt_nostrictsync, "nostrictsync" },
171 { Opt_strictsync, "strictsync" },
172 { Opt_serverino, "serverino" },
173 { Opt_noserverino, "noserverino" },
174 { Opt_rwpidforward, "rwpidforward" },
175 { Opt_cifsacl, "cifsacl" },
176 { Opt_nocifsacl, "nocifsacl" },
177 { Opt_acl, "acl" },
178 { Opt_noacl, "noacl" },
179 { Opt_locallease, "locallease" },
180 { Opt_sign, "sign" },
181 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400182 { Opt_noac, "noac" },
183 { Opt_fsc, "fsc" },
184 { Opt_mfsymlinks, "mfsymlinks" },
185 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400186 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400187 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500188 { Opt_persistent, "persistenthandles"},
189 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600190 { Opt_resilient, "resilienthandles"},
191 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530192 { Opt_domainauto, "domainauto"},
Long Li8339dd32017-11-07 01:54:55 -0700193 { Opt_rdma, "rdma"},
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400194
195 { Opt_backupuid, "backupuid=%s" },
196 { Opt_backupgid, "backupgid=%s" },
197 { Opt_uid, "uid=%s" },
198 { Opt_cruid, "cruid=%s" },
199 { Opt_gid, "gid=%s" },
200 { Opt_file_mode, "file_mode=%s" },
201 { Opt_dirmode, "dirmode=%s" },
202 { Opt_dirmode, "dir_mode=%s" },
203 { Opt_port, "port=%s" },
204 { Opt_rsize, "rsize=%s" },
205 { Opt_wsize, "wsize=%s" },
206 { Opt_actimeo, "actimeo=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600207 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500208 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600209 { Opt_snapshot, "snapshot=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400210
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100211 { Opt_blank_user, "user=" },
212 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400213 { Opt_user, "user=%s" },
214 { Opt_user, "username=%s" },
215 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100216 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400217 { Opt_pass, "pass=%s" },
218 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100219 { Opt_blank_ip, "ip=" },
220 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400221 { Opt_ip, "ip=%s" },
222 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400223 { Opt_ignore, "unc=%s" },
224 { Opt_ignore, "target=%s" },
225 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400226 { Opt_domain, "dom=%s" },
227 { Opt_domain, "domain=%s" },
228 { Opt_domain, "workgroup=%s" },
229 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400230 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400231 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400232 { Opt_netbiosname, "netbiosname=%s" },
233 { Opt_servern, "servern=%s" },
234 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400235 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400236 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400237 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400238
239 { Opt_ignore, "cred" },
240 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400241 { Opt_ignore, "cred=%s" },
242 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400243 { Opt_ignore, "guest" },
244 { Opt_ignore, "rw" },
245 { Opt_ignore, "ro" },
246 { Opt_ignore, "suid" },
247 { Opt_ignore, "nosuid" },
248 { Opt_ignore, "exec" },
249 { Opt_ignore, "noexec" },
250 { Opt_ignore, "nodev" },
251 { Opt_ignore, "noauto" },
252 { Opt_ignore, "dev" },
253 { Opt_ignore, "mand" },
254 { Opt_ignore, "nomand" },
255 { Opt_ignore, "_netdev" },
256
257 { Opt_err, NULL }
258};
259
260enum {
261 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
262 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400263 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
264 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400265 Opt_sec_none,
266
267 Opt_sec_err
268};
269
270static const match_table_t cifs_secflavor_tokens = {
271 { Opt_sec_krb5, "krb5" },
272 { Opt_sec_krb5i, "krb5i" },
273 { Opt_sec_krb5p, "krb5p" },
274 { Opt_sec_ntlmsspi, "ntlmsspi" },
275 { Opt_sec_ntlmssp, "ntlmssp" },
276 { Opt_ntlm, "ntlm" },
277 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400278 { Opt_sec_ntlmv2, "nontlm" },
279 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400280 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400281 { Opt_sec_lanman, "lanman" },
282 { Opt_sec_none, "none" },
283
284 { Opt_sec_err, NULL }
285};
286
Jeff Layton15b6a472012-05-16 07:50:15 -0400287/* cache flavors */
288enum {
289 Opt_cache_loose,
290 Opt_cache_strict,
291 Opt_cache_none,
292 Opt_cache_err
293};
294
295static const match_table_t cifs_cacheflavor_tokens = {
296 { Opt_cache_loose, "loose" },
297 { Opt_cache_strict, "strict" },
298 { Opt_cache_none, "none" },
299 { Opt_cache_err, NULL }
300};
301
Jeff Layton23db65f2012-05-15 12:20:51 -0400302static const match_table_t cifs_smb_version_tokens = {
303 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600304 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000305 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500306 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500307 { Smb_302, SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600308 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500309 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French9764c022017-09-17 10:41:35 -0500310 { Smb_3any, SMB3ANY_VERSION_STRING },
311 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600312 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400313};
314
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300315static int ip_connect(struct TCP_Server_Info *server);
316static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400317static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400318static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400319static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -0500320 const char *devname, bool is_smb3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Jeff Laytond5c56052008-12-01 18:42:33 -0500322/*
Paulo Alcantarac0be6242018-11-20 15:16:36 -0200323 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
324 * get their ip addresses changed at some point.
325 *
326 * This should be called with server->srv_mutex held.
327 */
328#ifdef CONFIG_CIFS_DFS_UPCALL
329static int reconn_set_ipaddr(struct TCP_Server_Info *server)
330{
331 int rc;
332 int len;
333 char *unc, *ipaddr = NULL;
334
335 if (!server->hostname)
336 return -EINVAL;
337
338 len = strlen(server->hostname) + 3;
339
340 unc = kmalloc(len, GFP_KERNEL);
341 if (!unc) {
342 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
343 return -ENOMEM;
344 }
345 snprintf(unc, len, "\\\\%s", server->hostname);
346
347 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
348 kfree(unc);
349
350 if (rc < 0) {
351 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
352 __func__, server->hostname, rc);
353 return rc;
354 }
355
356 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
357 strlen(ipaddr));
358 kfree(ipaddr);
359
360 return !rc ? -1 : 0;
361}
362#else
363static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
364{
365 return 0;
366}
367#endif
368
369/*
Jeff Laytond5c56052008-12-01 18:42:33 -0500370 * cifs tcp session reconnection
371 *
372 * mark tcp session as reconnecting so temporarily locked
373 * mark all smb sessions as reconnecting for tcp session
374 * reconnect tcp session
375 * wake up waiters on reconnection? - (not needed currently)
376 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400377int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378cifs_reconnect(struct TCP_Server_Info *server)
379{
380 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500381 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000382 struct cifs_ses *ses;
383 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000384 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400385 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000386
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000388 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000389 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 next time through the loop */
391 spin_unlock(&GlobalMid_Lock);
392 return rc;
393 } else
394 server->tcpStatus = CifsNeedReconnect;
395 spin_unlock(&GlobalMid_Lock);
396 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400397 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
Joe Perchesf96637b2013-05-04 22:12:25 -0500399 cifs_dbg(FYI, "Reconnecting tcp session\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500400 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
402 /* before reconnecting the tcp session, mark the smb session (uid)
403 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500404 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
405 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530406 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500407 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000408 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500409 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500410 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000411 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500412 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100414 if (ses->tcon_ipc)
415 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530417 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500418
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500420 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500421 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000422 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500423 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
424 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800425 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500426 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
427 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 sock_release(server->ssocket);
429 server->ssocket = NULL;
430 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500431 server->sequence_number = 0;
432 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500433 kfree(server->session_key.response);
434 server->session_key.response = NULL;
435 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000436 server->lstrp = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500438 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400439 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500440 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500442 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
443 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400444 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
445 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400446 list_move(&mid_entry->qhead, &retry_list);
447 }
448 spin_unlock(&GlobalMid_Lock);
Rabin Vincent820962d2015-12-23 07:32:41 +0100449 mutex_unlock(&server->srv_mutex);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400450
Joe Perchesf96637b2013-05-04 22:12:25 -0500451 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400452 list_for_each_safe(tmp, tmp2, &retry_list) {
453 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500454 list_del_init(&mid_entry->qhead);
455 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400458 do {
Steve French6c3d8902006-07-31 22:46:20 +0000459 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300460
461 /* we should try only the port we connected to before */
Jeff Layton73e216a2013-09-05 08:38:10 -0400462 mutex_lock(&server->srv_mutex);
Long Li781a8052017-11-22 17:38:36 -0700463 if (cifs_rdma_enabled(server))
464 rc = smbd_reconnect(server);
465 else
466 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000467 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500468 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantarac0be6242018-11-20 15:16:36 -0200469 rc = reconn_set_ipaddr(server);
470 if (rc) {
471 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
472 __func__, rc);
473 }
Federico Sauter4afe2602015-03-17 17:45:28 +0100474 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700475 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 } else {
477 atomic_inc(&tcpSesReconnectCount);
478 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000479 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000480 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000481 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100482 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400484 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500485
Sachin Prabhub8c60012016-10-20 19:52:24 -0400486 if (server->tcpStatus == CifsNeedNegotiate)
487 mod_delayed_work(cifsiod_wq, &server->echo, 0);
488
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 return rc;
490}
491
Jeff Laytonc74093b2011-01-11 07:24:23 -0500492static void
493cifs_echo_request(struct work_struct *work)
494{
495 int rc;
496 struct TCP_Server_Info *server = container_of(work,
497 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400498 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500499
Jeff Layton247ec9b2011-02-04 17:09:50 -0500500 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400501 * If we need to renegotiate, set echo interval to zero to
502 * immediately call echo service where we can renegotiate.
503 */
504 if (server->tcpStatus == CifsNeedNegotiate)
505 echo_interval = 0;
506 else
507 echo_interval = server->echo_interval;
508
509 /*
510 * We cannot send an echo if it is disabled.
511 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500512 */
Steve French4fcd1812016-06-22 20:12:05 -0500513
514 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400515 server->tcpStatus == CifsExiting ||
516 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400517 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600518 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500519 goto requeue_echo;
520
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400521 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500522 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500523 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
524 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500525
526requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400527 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500528}
529
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400530static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400531allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400532{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400533 if (!server->bigbuf) {
534 server->bigbuf = (char *)cifs_buf_get();
535 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500536 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400537 msleep(3000);
538 /* retry will check if exiting */
539 return false;
540 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400541 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400542 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400543 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400544 }
545
Jeff Layton2a37ef92011-10-19 15:29:23 -0400546 if (!server->smallbuf) {
547 server->smallbuf = (char *)cifs_small_buf_get();
548 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500549 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400550 msleep(1000);
551 /* retry will check if exiting */
552 return false;
553 }
554 /* beginning of smb buffer is cleared in our buf_get */
555 } else {
556 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400557 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400558 }
559
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400560 return true;
561}
562
Jeff Laytonba749e62011-10-11 06:41:32 -0400563static bool
564server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400565{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300566 /*
Ronnie Sahlbergd29fbf62019-07-06 06:52:46 +1000567 * We need to wait 3 echo intervals to make sure we handle such
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300568 * situations right:
569 * 1s client sends a normal SMB request
Ronnie Sahlbergd29fbf62019-07-06 06:52:46 +1000570 * 3s client gets a response
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300571 * 30s echo workqueue job pops, and decides we got a response recently
572 * and don't need to send another
573 * ...
574 * 65s kernel_recvmsg times out, and we see that we haven't gotten
575 * a response in >60s.
576 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200577 if ((server->tcpStatus == CifsGood ||
578 server->tcpStatus == CifsNeedNegotiate) &&
Ronnie Sahlbergd29fbf62019-07-06 06:52:46 +1000579 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600580 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
Ronnie Sahlbergd29fbf62019-07-06 06:52:46 +1000581 server->hostname, (3 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400582 cifs_reconnect(server);
583 wake_up(&server->response_q);
584 return true;
585 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400586
Jeff Laytonba749e62011-10-11 06:41:32 -0400587 return false;
588}
589
Pavel Shilovsky779c65b2019-01-18 17:25:36 -0800590static inline bool
591zero_credits(struct TCP_Server_Info *server)
592{
593 int val;
594
595 spin_lock(&server->req_lock);
596 val = server->credits + server->echo_credits + server->oplock_credits;
597 if (server->in_flight == 0 && val == 0) {
598 spin_unlock(&server->req_lock);
599 return true;
600 }
601 spin_unlock(&server->req_lock);
602 return false;
603}
604
Al Viro71335662016-01-09 19:54:50 -0500605static int
606cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400607{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400608 int length = 0;
609 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400610
Al Viro71335662016-01-09 19:54:50 -0500611 smb_msg->msg_control = NULL;
612 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400613
Al Viro71335662016-01-09 19:54:50 -0500614 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500615 try_to_freeze();
616
Pavel Shilovsky779c65b2019-01-18 17:25:36 -0800617 /* reconnect if no credits and no requests in flight */
618 if (zero_credits(server)) {
619 cifs_reconnect(server);
620 return -ECONNABORTED;
621 }
622
Al Viro71335662016-01-09 19:54:50 -0500623 if (server_unresponsive(server))
624 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700625 if (cifs_rdma_enabled(server) && server->smbd_conn)
626 length = smbd_recv(server->smbd_conn, smb_msg);
627 else
628 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500629
630 if (server->tcpStatus == CifsExiting)
631 return -ESHUTDOWN;
632
633 if (server->tcpStatus == CifsNeedReconnect) {
634 cifs_reconnect(server);
635 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400636 }
637
Al Viro71335662016-01-09 19:54:50 -0500638 if (length == -ERESTARTSYS ||
639 length == -EAGAIN ||
640 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400641 /*
642 * Minimum sleep to prevent looping, allowing socket
643 * to clear and app threads to set tcpStatus
644 * CifsNeedReconnect if server hung.
645 */
646 usleep_range(1000, 2000);
647 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400648 continue;
Al Viro71335662016-01-09 19:54:50 -0500649 }
650
651 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500652 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400653 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500654 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400655 }
656 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400657 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400658}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400659
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400660int
661cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
662 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400663{
Al Viro71335662016-01-09 19:54:50 -0500664 struct msghdr smb_msg;
665 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
666 iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400667
Al Viro71335662016-01-09 19:54:50 -0500668 return cifs_readv_from_socket(server, &smb_msg);
669}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400670
Al Viro71335662016-01-09 19:54:50 -0500671int
672cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700673 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500674{
675 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700676 struct bio_vec bv = {
677 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
Al Viro71335662016-01-09 19:54:50 -0500678 iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
679 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400680}
681
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400682static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400683is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400684{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400685 /*
686 * The first byte big endian of the length field,
687 * is actually not part of the length but the type
688 * with the most common, zero, as regular data.
689 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400690 switch (type) {
691 case RFC1002_SESSION_MESSAGE:
692 /* Regular SMB response */
693 return true;
694 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500695 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400696 break;
697 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500698 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400699 break;
700 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400701 /*
702 * We get this from Windows 98 instead of an error on
703 * SMB negprot response.
704 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500705 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400706 /* give server a second to clean up */
707 msleep(1000);
708 /*
709 * Always try 445 first on reconnect since we get NACK
710 * on some if we ever connected to port 139 (the NACK
711 * is since we do not begin with RFC1001 session
712 * initialize frame).
713 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400714 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400715 cifs_reconnect(server);
716 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400717 break;
718 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500719 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400720 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400721 }
722
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400723 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400724}
725
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400726void
727dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400728{
729#ifdef CONFIG_CIFS_STATS2
730 mid->when_received = jiffies;
731#endif
732 spin_lock(&GlobalMid_Lock);
733 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400734 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400735 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400736 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000737 /*
738 * Trying to handle/dequeue a mid after the send_recv()
739 * function has finished processing it is a bug.
740 */
741 if (mid->mid_flags & MID_DELETED)
742 printk_once(KERN_WARNING
743 "trying to dequeue a deleted mid\n");
744 else
745 list_del_init(&mid->qhead);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400746 spin_unlock(&GlobalMid_Lock);
747}
748
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400749static void
750handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400751 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400752{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400753 if (server->ops->check_trans2 &&
754 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400755 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400756 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400757 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400758 /* Was previous buf put in mpx struct for multi-rsp? */
759 if (!mid->multiRsp) {
760 /* smb buffer will be freed by user thread */
761 if (server->large_buf)
762 server->bigbuf = NULL;
763 else
764 server->smallbuf = NULL;
765 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400766 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400767}
768
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400769static void clean_demultiplex_info(struct TCP_Server_Info *server)
770{
771 int length;
772
773 /* take it off the list, if it's not already */
774 spin_lock(&cifs_tcp_ses_lock);
775 list_del_init(&server->tcp_ses_list);
776 spin_unlock(&cifs_tcp_ses_lock);
777
778 spin_lock(&GlobalMid_Lock);
779 server->tcpStatus = CifsExiting;
780 spin_unlock(&GlobalMid_Lock);
781 wake_up_all(&server->response_q);
782
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400783 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300784 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400785 if (server->credits <= 0)
786 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300787 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400788 /*
789 * Although there should not be any requests blocked on this queue it
790 * can not hurt to be paranoid and try to wake up requests that may
791 * haven been blocked when more than 50 at time were on the wire to the
792 * same server - they now will see the session is in exit state and get
793 * out of SendReceive.
794 */
795 wake_up_all(&server->request_q);
796 /* give those requests time to exit */
797 msleep(125);
Long Libce9ce72017-11-22 17:38:38 -0700798 if (cifs_rdma_enabled(server) && server->smbd_conn) {
799 smbd_destroy(server->smbd_conn);
800 server->smbd_conn = NULL;
801 }
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400802 if (server->ssocket) {
803 sock_release(server->ssocket);
804 server->ssocket = NULL;
805 }
806
807 if (!list_empty(&server->pending_mid_q)) {
808 struct list_head dispose_list;
809 struct mid_q_entry *mid_entry;
810 struct list_head *tmp, *tmp2;
811
812 INIT_LIST_HEAD(&dispose_list);
813 spin_lock(&GlobalMid_Lock);
814 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
815 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500816 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400817 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400818 list_move(&mid_entry->qhead, &dispose_list);
819 }
820 spin_unlock(&GlobalMid_Lock);
821
822 /* now walk dispose list and issue callbacks */
823 list_for_each_safe(tmp, tmp2, &dispose_list) {
824 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500825 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400826 list_del_init(&mid_entry->qhead);
827 mid_entry->callback(mid_entry);
828 }
829 /* 1/8th of sec is more than enough time for them to exit */
830 msleep(125);
831 }
832
833 if (!list_empty(&server->pending_mid_q)) {
834 /*
835 * mpx threads have not exited yet give them at least the smb
836 * send timeout time for long ops.
837 *
838 * Due to delays on oplock break requests, we need to wait at
839 * least 45 seconds before giving up on a request getting a
840 * response and going ahead and killing cifsd.
841 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500842 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400843 msleep(46000);
844 /*
845 * If threads still have not exited they are probably never
846 * coming home not much else we can do but free the memory.
847 */
848 }
849
850 kfree(server->hostname);
851 kfree(server);
852
853 length = atomic_dec_return(&tcpSesAllocCount);
854 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700855 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400856}
857
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400858static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400859standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
860{
861 int length;
862 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +1000863 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400864
865 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100866 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
867 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500868 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400869 cifs_reconnect(server);
870 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400871 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400872 }
873
874 /* switch to large buffer if too big for a small one */
875 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
876 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400877 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400878 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400879 }
880
881 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400882 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100883 pdu_length - HEADER_SIZE(server) + 1
884 + server->vals->header_preamble_size);
885
Jeff Laytone9097ab2011-10-19 15:29:40 -0400886 if (length < 0)
887 return length;
888 server->total_read += length;
889
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400890 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400891
Pavel Shilovsky4326ed22016-11-17 15:24:46 -0800892 return cifs_handle_standard(server, mid);
893}
894
895int
896cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
897{
898 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
899 int length;
900
Jeff Laytone9097ab2011-10-19 15:29:40 -0400901 /*
902 * We know that we received enough to get to the MID as we
903 * checked the pdu_length earlier. Now check to see
904 * if the rest of the header is OK. We borrow the length
905 * var for the rest of the loop to avoid a new stack var.
906 *
907 * 48 bytes is enough to display the header and a little bit
908 * into the payload for debugging purposes.
909 */
Steve French373512e2015-12-18 13:05:30 -0600910 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400911 if (length != 0)
912 cifs_dump_mem("Bad SMB: ", buf,
913 min_t(unsigned int, server->total_read, 48));
914
Pavel Shilovsky511c54a2017-07-08 14:32:00 -0700915 if (server->ops->is_session_expired &&
916 server->ops->is_session_expired(buf)) {
917 cifs_reconnect(server);
918 wake_up(&server->response_q);
919 return -1;
920 }
921
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700922 if (server->ops->is_status_pending &&
923 server->ops->is_status_pending(buf, server, length))
924 return -1;
925
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500926 if (!mid)
927 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400928
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400929 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500930 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400931}
932
Ronnie Sahlbergb73132b2019-02-05 12:56:44 +1000933static void
934smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
935{
936 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
937
938 /*
939 * SMB1 does not use credits.
940 */
941 if (server->vals->header_preamble_size)
942 return;
943
944 if (shdr->CreditRequest) {
945 spin_lock(&server->req_lock);
946 server->credits += le16_to_cpu(shdr->CreditRequest);
947 spin_unlock(&server->req_lock);
948 wake_up(&server->request_q);
949 }
950}
951
952
Jeff Laytone9097ab2011-10-19 15:29:40 -0400953static int
Al Viro7c97c202011-06-21 08:51:28 -0400954cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +1000956 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -0400957 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400958 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +1000959 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400960 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500961 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +1000962 struct mid_q_entry *mids[MAX_COMPOUND];
963 char *bufs[MAX_COMPOUND];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -0500966 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400967
968 length = atomic_inc_return(&tcpSesAllocCount);
969 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -0700970 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700972 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +0000973 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700974 if (try_to_freeze())
975 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700976
Jeff Layton2a37ef92011-10-19 15:29:23 -0400977 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400978 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700979
Jeff Layton2a37ef92011-10-19 15:29:23 -0400980 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400981 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000982 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000983
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400984 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400985 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +0000986 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +1000987
988 if (server->vals->header_preamble_size == 0)
989 server->total_read = 0;
990 else
991 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700992
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400993 /*
994 * The right amount was read from socket - 4 bytes,
995 * so we can now interpret the length field.
996 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400997 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -0700998
Joe Perchesf96637b2013-05-04 22:12:25 -0500999 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001000 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001001 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001002next_pdu:
1003 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001004
Jeff Layton89482a52011-10-19 15:28:57 -04001005 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001006 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001007 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001008 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001009 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001010 cifs_reconnect(server);
1011 wake_up(&server->response_q);
1012 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001013 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001014
Jeff Layton89482a52011-10-19 15:28:57 -04001015 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001016 length = cifs_read_from_socket(server,
1017 buf + server->vals->header_preamble_size,
1018 HEADER_SIZE(server) - 1
1019 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001020 if (length < 0)
1021 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001022 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001023
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001024 if (server->ops->next_header) {
1025 next_offset = server->ops->next_header(buf);
1026 if (next_offset)
1027 server->pdu_size = next_offset;
1028 }
1029
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001030 memset(mids, 0, sizeof(mids));
1031 memset(bufs, 0, sizeof(bufs));
1032 num_mids = 0;
1033
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001034 if (server->ops->is_transform_hdr &&
1035 server->ops->receive_transform &&
1036 server->ops->is_transform_hdr(buf)) {
1037 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001038 mids,
1039 bufs,
1040 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001041 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001042 mids[0] = server->ops->find_mid(server, buf);
1043 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001044 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001045
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001046 if (!mids[0] || !mids[0]->receive)
1047 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001048 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001049 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001050 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001051
Lars Persson696e4202018-06-25 14:05:25 +02001052 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001053 for (i = 0; i < num_mids; i++)
1054 if (mids[i])
1055 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001056 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001057 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001058
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001059 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -04001060 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -07001061
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001062
Steve Frenchfda35942011-01-20 18:06:34 +00001063 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001064
1065 for (i = 0; i < num_mids; i++) {
1066 if (mids[i] != NULL) {
1067 mids[i]->resp_buf_size = server->pdu_size;
1068 if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
1069 mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
1070 server->ops->handle_cancelled_mid)
1071 server->ops->handle_cancelled_mid(
1072 mids[i]->resp_buf,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001073 server);
1074
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001075 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1076 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001077
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001078 cifs_mid_q_entry_release(mids[i]);
1079 } else if (server->ops->is_oplock_break &&
1080 server->ops->is_oplock_break(bufs[i],
1081 server)) {
Ronnie Sahlbergb73132b2019-02-05 12:56:44 +10001082 smb2_add_credits_from_hdr(bufs[i], server);
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001083 cifs_dbg(FYI, "Received oplock break\n");
1084 } else {
1085 cifs_dbg(VFS, "No task to wake, unknown frame "
1086 "received! NumMids %d\n",
1087 atomic_read(&midCount));
1088 cifs_dump_mem("Received Data is: ", bufs[i],
1089 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +00001090#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001091 if (server->ops->dump_detail)
1092 server->ops->dump_detail(bufs[i],
1093 server);
Ronnie Sahlbergb73132b2019-02-05 12:56:44 +10001094 smb2_add_credits_from_hdr(bufs[i], server);
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001095 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001096#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001097 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001098 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001099
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001100 if (pdu_length > server->pdu_size) {
1101 if (!allocate_buffers(server))
1102 continue;
1103 pdu_length -= server->pdu_size;
1104 server->total_read = 0;
1105 server->large_buf = false;
1106 buf = server->smallbuf;
1107 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001108 }
1109 } /* end while !EXITING */
1110
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001111 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001112 cifs_buf_release(server->bigbuf);
1113 if (server->smallbuf) /* no sense logging a debug message if NULL */
1114 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001116 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001117 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001118
1119 /* if server->tsk was NULL then wait for a signal before exiting */
1120 if (!task_to_wake) {
1121 set_current_state(TASK_INTERRUPTIBLE);
1122 while (!signal_pending(current)) {
1123 schedule();
1124 set_current_state(TASK_INTERRUPTIBLE);
1125 }
1126 set_current_state(TASK_RUNNING);
1127 }
1128
Jeff Layton0468a2c2008-12-01 07:09:35 -05001129 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130}
1131
Jeff Laytonc359cf32007-11-16 22:22:06 +00001132/* extract the host portion of the UNC string */
1133static char *
1134extract_hostname(const char *unc)
1135{
1136 const char *src;
1137 char *dst, *delim;
1138 unsigned int len;
1139
1140 /* skip double chars at beginning of string */
1141 /* BB: check validity of these bytes? */
1142 src = unc + 2;
1143
1144 /* delimiter between hostname and sharename is always '\\' now */
1145 delim = strchr(src, '\\');
1146 if (!delim)
1147 return ERR_PTR(-EINVAL);
1148
1149 len = delim - src;
1150 dst = kmalloc((len + 1), GFP_KERNEL);
1151 if (dst == NULL)
1152 return ERR_PTR(-ENOMEM);
1153
1154 memcpy(dst, src, len);
1155 dst[len] = '\0';
1156
1157 return dst;
1158}
1159
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001160static int get_option_ul(substring_t args[], unsigned long *option)
1161{
1162 int rc;
1163 char *string;
1164
1165 string = match_strdup(args);
1166 if (string == NULL)
1167 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001168 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001169 kfree(string);
1170
1171 return rc;
1172}
1173
Eric W. Biederman3da46562013-02-06 01:37:39 -08001174static int get_option_uid(substring_t args[], kuid_t *result)
1175{
1176 unsigned long value;
1177 kuid_t uid;
1178 int rc;
1179
1180 rc = get_option_ul(args, &value);
1181 if (rc)
1182 return rc;
1183
1184 uid = make_kuid(current_user_ns(), value);
1185 if (!uid_valid(uid))
1186 return -EINVAL;
1187
1188 *result = uid;
1189 return 0;
1190}
1191
1192static int get_option_gid(substring_t args[], kgid_t *result)
1193{
1194 unsigned long value;
1195 kgid_t gid;
1196 int rc;
1197
1198 rc = get_option_ul(args, &value);
1199 if (rc)
1200 return rc;
1201
1202 gid = make_kgid(current_user_ns(), value);
1203 if (!gid_valid(gid))
1204 return -EINVAL;
1205
1206 *result = gid;
1207 return 0;
1208}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001209
1210static int cifs_parse_security_flavors(char *value,
1211 struct smb_vol *vol)
1212{
1213
1214 substring_t args[MAX_OPT_ARGS];
1215
Jeff Layton1e3cc572013-06-10 17:12:23 -05001216 /*
1217 * With mount options, the last one should win. Reset any existing
1218 * settings back to default.
1219 */
1220 vol->sectype = Unspecified;
1221 vol->sign = false;
1222
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001223 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001224 case Opt_sec_krb5p:
1225 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1226 return 1;
1227 case Opt_sec_krb5i:
1228 vol->sign = true;
1229 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001230 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001231 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001232 break;
1233 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001234 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001235 /* Fallthrough */
1236 case Opt_sec_ntlmssp:
1237 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001238 break;
1239 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001240 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001241 /* Fallthrough */
1242 case Opt_ntlm:
1243 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001244 break;
1245 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001246 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001247 /* Fallthrough */
1248 case Opt_sec_ntlmv2:
1249 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001250 break;
1251#ifdef CONFIG_CIFS_WEAK_PW_HASH
1252 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001253 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001254 break;
1255#endif
1256 case Opt_sec_none:
1257 vol->nullauth = 1;
1258 break;
1259 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001260 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001261 return 1;
1262 }
1263
1264 return 0;
1265}
1266
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001268cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1269{
1270 substring_t args[MAX_OPT_ARGS];
1271
1272 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1273 case Opt_cache_loose:
1274 vol->direct_io = false;
1275 vol->strict_io = false;
1276 break;
1277 case Opt_cache_strict:
1278 vol->direct_io = false;
1279 vol->strict_io = true;
1280 break;
1281 case Opt_cache_none:
1282 vol->direct_io = true;
1283 vol->strict_io = false;
1284 break;
1285 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001286 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001287 return 1;
1288 }
1289 return 0;
1290}
1291
1292static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001293cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001294{
1295 substring_t args[MAX_OPT_ARGS];
1296
1297 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001298#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001299 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001300 if (disable_legacy_dialects) {
1301 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1302 return 1;
1303 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001304 if (is_smb3) {
1305 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1306 return 1;
1307 }
Jeff Layton23db65f2012-05-15 12:20:51 -04001308 vol->ops = &smb1_operations;
1309 vol->vals = &smb1_values;
1310 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001311 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001312 if (disable_legacy_dialects) {
1313 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1314 return 1;
1315 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001316 if (is_smb3) {
1317 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1318 return 1;
1319 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001320 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001321 vol->vals = &smb20_values;
1322 break;
Steve French74204512018-06-19 14:34:08 -05001323#else
1324 case Smb_1:
1325 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1326 return 1;
1327 case Smb_20:
1328 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1329 return 1;
1330#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001331 case Smb_21:
1332 vol->ops = &smb21_operations;
1333 vol->vals = &smb21_values;
1334 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001335 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001336 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001337 vol->vals = &smb30_values;
1338 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001339 case Smb_302:
1340 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1341 vol->vals = &smb302_values;
1342 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001343 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001344 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001345 vol->vals = &smb311_values;
1346 break;
Steve French9764c022017-09-17 10:41:35 -05001347 case Smb_3any:
1348 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1349 vol->vals = &smb3any_values;
1350 break;
1351 case Smb_default:
1352 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1353 vol->vals = &smbdefault_values;
1354 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001355 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001356 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001357 return 1;
1358 }
1359 return 0;
1360}
1361
Jeff Laytond387a5c2012-12-10 06:10:46 -05001362/*
1363 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1364 * fields with the result. Returns 0 on success and an error otherwise.
1365 */
1366static int
1367cifs_parse_devname(const char *devname, struct smb_vol *vol)
1368{
1369 char *pos;
1370 const char *delims = "/\\";
1371 size_t len;
1372
Yao Liu36a32192019-01-28 19:47:28 +08001373 if (unlikely(!devname || !*devname)) {
1374 cifs_dbg(VFS, "Device name not specified.\n");
1375 return -EINVAL;
1376 }
1377
Jeff Laytond387a5c2012-12-10 06:10:46 -05001378 /* make sure we have a valid UNC double delimiter prefix */
1379 len = strspn(devname, delims);
1380 if (len != 2)
1381 return -EINVAL;
1382
1383 /* find delimiter between host and sharename */
1384 pos = strpbrk(devname + 2, delims);
1385 if (!pos)
1386 return -EINVAL;
1387
1388 /* skip past delimiter */
1389 ++pos;
1390
1391 /* now go until next delimiter or end of string */
1392 len = strcspn(pos, delims);
1393
1394 /* move "pos" up to delimiter or NULL */
1395 pos += len;
1396 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1397 if (!vol->UNC)
1398 return -ENOMEM;
1399
1400 convert_delimiter(vol->UNC, '\\');
1401
Sachin Prabhu11e31642016-02-08 13:44:01 +05301402 /* skip any delimiter */
1403 if (*pos == '/' || *pos == '\\')
1404 pos++;
1405
1406 /* If pos is NULL then no prepath */
1407 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001408 return 0;
1409
1410 vol->prepath = kstrdup(pos, GFP_KERNEL);
1411 if (!vol->prepath)
1412 return -ENOMEM;
1413
1414 return 0;
1415}
1416
Jeff Layton23db65f2012-05-15 12:20:51 -04001417static int
Sean Finneyb9468452011-04-11 13:19:32 +00001418cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001419 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001421 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001422 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 unsigned int temp_len, i, j;
1424 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001425 short int override_uid = -1;
1426 short int override_gid = -1;
1427 bool uid_specified = false;
1428 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001429 bool sloppy = false;
1430 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001431 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001432 char *string = NULL;
1433 char *tmp_end, *value;
1434 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001435 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001436 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001437 unsigned short port = 0;
1438 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
1440 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001441 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001442 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Jeff Layton6ee95422012-11-26 11:09:57 -05001444 /* ensure we always start with zeroed-out smb_vol */
1445 memset(vol, 0, sizeof(*vol));
1446
Jeff Layton88463992010-11-22 15:31:03 -05001447 /*
1448 * does not have to be perfect mapping since field is
1449 * informational, only used for servers that do not support
1450 * port 445 and it can be overridden at mount time
1451 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001452 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1453 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001454 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1455
Jeff Layton1397f2e2011-01-07 11:30:28 -05001456 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001457 /* null target name indicates to use *SMBSERVR default called name
1458 if we end up sending RFC1001 session initialize */
1459 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001460 vol->cred_uid = current_uid();
1461 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001462 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001463
Steve French2baa2682014-09-27 02:19:01 -05001464 /*
1465 * default to SFM style remapping of seven reserved characters
1466 * unless user overrides it or we negotiate CIFS POSIX where
1467 * it is unnecessary. Can not simultaneously use more than one mapping
1468 * since then readdir could list files that open could not open
1469 */
1470 vol->remap = true;
1471
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001472 /* default to only allowing write access to owner of the mount */
1473 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474
1475 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001476 /* default is always to request posix paths. */
1477 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001478 /* default to using server inode numbers where available */
1479 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001480
Jeff Layton1b359202012-09-19 15:20:27 -07001481 /* default is to use strict cifs caching semantics */
1482 vol->strict_io = true;
1483
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301484 vol->actimeo = CIFS_DEF_ACTIMEO;
1485
Steve French9764c022017-09-17 10:41:35 -05001486 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1487 vol->ops = &smb30_operations;
1488 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001489
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001490 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1491
Sean Finneyb9468452011-04-11 13:19:32 +00001492 if (!mountdata)
1493 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
Sean Finneyb9468452011-04-11 13:19:32 +00001495 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1496 if (!mountdata_copy)
1497 goto cifs_parse_mount_err;
1498
1499 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001500 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001501
Steve French50c2f752007-07-13 00:33:32 +00001502 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001503 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 separator[0] = options[4];
1505 options += 5;
1506 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001507 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 }
1509 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001510 vol->backupuid_specified = false; /* no backup intent for a user */
1511 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001512
Jeff Layton37d4f992013-05-24 07:40:05 -04001513 switch (cifs_parse_devname(devname, vol)) {
1514 case 0:
1515 break;
1516 case -ENOMEM:
1517 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1518 goto cifs_parse_mount_err;
1519 case -EINVAL:
1520 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1521 goto cifs_parse_mount_err;
1522 default:
1523 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1524 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001525 }
1526
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001528 substring_t args[MAX_OPT_ARGS];
1529 unsigned long option;
1530 int token;
1531
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 if (!*data)
1533 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001535 token = match_token(data, cifs_mount_option_tokens, args);
1536
1537 switch (token) {
1538
1539 /* Ingnore the following */
1540 case Opt_ignore:
1541 break;
1542
1543 /* Boolean values */
1544 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001546 break;
1547 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001549 break;
1550 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001551 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001552 break;
1553 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001554 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001555 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001556 case Opt_forcegid:
1557 override_gid = 1;
1558 break;
1559 case Opt_noforcegid:
1560 override_gid = 0;
1561 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001562 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001563 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001564 break;
1565 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001566 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001567 break;
Steve French2e96c932019-09-11 21:46:20 -05001568 case Opt_nolease:
1569 vol->no_lease = 1;
1570 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001571 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001573 break;
1574 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001576 break;
1577 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001579 break;
1580 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001582 break;
1583 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001584 vol->sfu_remap = true;
1585 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001586 break;
1587 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001588 vol->sfu_remap = false;
1589 break;
1590 case Opt_mapposix:
1591 vol->remap = true;
1592 vol->sfu_remap = false; /* disable SFU mapping */
1593 break;
1594 case Opt_nomapposix:
1595 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001596 break;
1597 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001598 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001599 break;
1600 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001601 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001602 break;
1603 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001604 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001605 break;
1606 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001607 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001608 break;
1609 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001610 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001611 break;
1612 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001613 if (vol->linux_ext)
1614 cifs_dbg(VFS,
1615 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001616 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001617 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001618 case Opt_unix:
1619 if (vol->no_linux_ext)
1620 cifs_dbg(VFS,
1621 "conflicting unix mount options\n");
1622 vol->linux_ext = 1;
1623 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001624 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001625 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001626 break;
1627 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001628 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001629 break;
1630 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001631 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001632 /*
1633 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001634 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001635 * local vfs will do advisory
1636 */
Steve French50c2f752007-07-13 00:33:32 +00001637 if (vol->file_mode ==
1638 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001639 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001640 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001641 case Opt_nohandlecache:
1642 vol->nohandlecache = 1;
1643 break;
1644 case Opt_handlecache:
1645 vol->nohandlecache = 0;
1646 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001647 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001648 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001649 break;
1650 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001652 break;
1653 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001655 break;
Steve French95932652016-09-23 01:36:34 -05001656 case Opt_setuidfromacl:
1657 vol->setuidfromacl = 1;
1658 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001659 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001660 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001661 break;
1662 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001663 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001664 break;
1665 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001667 break;
1668 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001670 break;
1671 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001673 break;
1674 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001676 break;
1677 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001678 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001679 break;
1680 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001681 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001682 break;
1683 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001685 break;
1686 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001688 break;
1689 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001690 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001691 break;
1692 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001693 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001694 break;
1695 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001696 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001697 break;
1698 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001700 break;
1701 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001703 break;
1704 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001705 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001706 break;
1707 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001708 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001709 break;
1710 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001711 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001712 * is a per tree connection (mount) not a per socket
1713 * or per-smb connection option in the protocol
1714 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1715 */
Steve French95b1cb92008-05-15 16:44:38 +00001716 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001717 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001718 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001719 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001720 break;
1721 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301722#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001723 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001724 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301725#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301726 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001727 break;
1728 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001729 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001730 break;
1731 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001732 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001733 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001734 case Opt_sloppy:
1735 sloppy = true;
1736 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001737 case Opt_nosharesock:
1738 vol->nosharesock = true;
1739 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001740 case Opt_nopersistent:
1741 vol->nopersistent = true;
1742 if (vol->persistent) {
1743 cifs_dbg(VFS,
1744 "persistenthandles mount options conflict\n");
1745 goto cifs_parse_mount_err;
1746 }
1747 break;
1748 case Opt_persistent:
1749 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001750 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001751 cifs_dbg(VFS,
1752 "persistenthandles mount options conflict\n");
1753 goto cifs_parse_mount_err;
1754 }
1755 break;
Steve French592fafe2015-11-03 10:08:53 -06001756 case Opt_resilient:
1757 vol->resilient = true;
1758 if (vol->persistent) {
1759 cifs_dbg(VFS,
1760 "persistenthandles mount options conflict\n");
1761 goto cifs_parse_mount_err;
1762 }
1763 break;
1764 case Opt_noresilient:
1765 vol->resilient = false; /* already the default */
1766 break;
Germano Percossi39566442016-12-15 12:31:18 +05301767 case Opt_domainauto:
1768 vol->domainauto = true;
1769 break;
Long Li8339dd32017-11-07 01:54:55 -07001770 case Opt_rdma:
1771 vol->rdma = true;
1772 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001773
1774 /* Numeric Values */
1775 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001776 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001777 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1778 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001779 goto cifs_parse_mount_err;
1780 }
1781 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001782 break;
1783 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001784 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001785 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1786 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001787 goto cifs_parse_mount_err;
1788 }
1789 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001790 break;
1791 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001792 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001793 cifs_dbg(VFS, "%s: Invalid uid value\n",
1794 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001795 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001797 uid_specified = true;
1798 break;
1799 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001800 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001801 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1802 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 goto cifs_parse_mount_err;
1804 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001805 break;
1806 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001807 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001808 cifs_dbg(VFS, "%s: Invalid gid value\n",
1809 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001810 goto cifs_parse_mount_err;
1811 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001812 gid_specified = true;
1813 break;
1814 case Opt_file_mode:
1815 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001816 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1817 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001818 goto cifs_parse_mount_err;
1819 }
1820 vol->file_mode = option;
1821 break;
1822 case Opt_dirmode:
1823 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001824 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1825 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001826 goto cifs_parse_mount_err;
1827 }
1828 vol->dir_mode = option;
1829 break;
1830 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001831 if (get_option_ul(args, &option) ||
1832 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001833 cifs_dbg(VFS, "%s: Invalid port value\n",
1834 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001835 goto cifs_parse_mount_err;
1836 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001837 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001838 break;
1839 case Opt_rsize:
1840 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001841 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1842 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001843 goto cifs_parse_mount_err;
1844 }
1845 vol->rsize = option;
1846 break;
1847 case Opt_wsize:
1848 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001849 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1850 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001851 goto cifs_parse_mount_err;
1852 }
1853 vol->wsize = option;
1854 break;
1855 case Opt_actimeo:
1856 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001857 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1858 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001859 goto cifs_parse_mount_err;
1860 }
1861 vol->actimeo = HZ * option;
1862 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001863 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001864 goto cifs_parse_mount_err;
1865 }
1866 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06001867 case Opt_echo_interval:
1868 if (get_option_ul(args, &option)) {
1869 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
1870 __func__);
1871 goto cifs_parse_mount_err;
1872 }
1873 vol->echo_interval = option;
1874 break;
Steve French8b217fe2016-11-11 22:36:20 -06001875 case Opt_snapshot:
1876 if (get_option_ul(args, &option)) {
1877 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
1878 __func__);
1879 goto cifs_parse_mount_err;
1880 }
1881 vol->snapshot_time = option;
1882 break;
Steve French141891f2016-09-23 00:44:16 -05001883 case Opt_max_credits:
1884 if (get_option_ul(args, &option) || (option < 20) ||
1885 (option > 60000)) {
1886 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1887 __func__);
1888 goto cifs_parse_mount_err;
1889 }
1890 vol->max_credits = option;
1891 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001892
1893 /* String Arguments */
1894
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001895 case Opt_blank_user:
1896 /* null user, ie. anonymous authentication */
1897 vol->nullauth = 1;
1898 vol->username = NULL;
1899 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001900 case Opt_user:
1901 string = match_strdup(args);
1902 if (string == NULL)
1903 goto out_nomem;
1904
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001905 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1906 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001907 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001908 goto cifs_parse_mount_err;
1909 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001910
1911 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001912 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001913 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001914 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001915 break;
1916 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001917 /* passwords have to be handled differently
1918 * to allow the character used for deliminator
1919 * to be passed within them
1920 */
1921
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001922 /*
1923 * Check if this is a case where the password
1924 * starts with a delimiter
1925 */
1926 tmp_end = strchr(data, '=');
1927 tmp_end++;
1928 if (!(tmp_end < end && tmp_end[1] == delim)) {
1929 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01001930 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001931 vol->password = NULL;
1932 break;
1933 }
1934 /* Yes it is. Drop down to Opt_pass below.*/
1935 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001936 /* Obtain the value string */
1937 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001938 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001939
1940 /* Set tmp_end to end of the string */
1941 tmp_end = (char *) value + strlen(value);
1942
1943 /* Check if following character is the deliminator
1944 * If yes, we have encountered a double deliminator
1945 * reset the NULL character to the deliminator
1946 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301947 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001948 tmp_end[0] = delim;
1949
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301950 /* Keep iterating until we get to a single
1951 * deliminator OR the end
1952 */
1953 while ((tmp_end = strchr(tmp_end, delim))
1954 != NULL && (tmp_end[1] == delim)) {
1955 tmp_end = (char *) &tmp_end[2];
1956 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001957
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301958 /* Reset var options to point to next element */
1959 if (tmp_end) {
1960 tmp_end[0] = '\0';
1961 options = (char *) &tmp_end[1];
1962 } else
1963 /* Reached the end of the mount option
1964 * string */
1965 options = end;
1966 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001967
Aurelien Aptel97f4b722018-01-25 15:59:39 +01001968 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001969 /* Now build new password string */
1970 temp_len = strlen(value);
1971 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1972 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001973 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001974 goto cifs_parse_mount_err;
1975 }
1976
1977 for (i = 0, j = 0; i < temp_len; i++, j++) {
1978 vol->password[j] = value[i];
1979 if ((value[i] == delim) &&
1980 value[i+1] == delim)
1981 /* skip the second deliminator */
1982 i++;
1983 }
1984 vol->password[j] = '\0';
1985 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001986 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001987 /* FIXME: should this be an error instead? */
1988 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001989 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001990 case Opt_ip:
1991 string = match_strdup(args);
1992 if (string == NULL)
1993 goto out_nomem;
1994
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001995 if (!cifs_convert_address(dstaddr, string,
1996 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001997 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001998 goto cifs_parse_mount_err;
1999 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002000 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002001 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002002 case Opt_domain:
2003 string = match_strdup(args);
2004 if (string == NULL)
2005 goto out_nomem;
2006
Chen Gang057d6332013-07-19 09:01:36 +08002007 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2008 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002009 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002010 goto cifs_parse_mount_err;
2011 }
2012
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002013 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002014 vol->domainname = kstrdup(string, GFP_KERNEL);
2015 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002016 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002017 goto cifs_parse_mount_err;
2018 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002019 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002020 break;
2021 case Opt_srcaddr:
2022 string = match_strdup(args);
2023 if (string == NULL)
2024 goto out_nomem;
2025
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002026 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002027 (struct sockaddr *)&vol->srcaddr,
2028 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002029 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2030 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002031 goto cifs_parse_mount_err;
2032 }
2033 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002034 case Opt_iocharset:
2035 string = match_strdup(args);
2036 if (string == NULL)
2037 goto out_nomem;
2038
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002039 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002040 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002041 goto cifs_parse_mount_err;
2042 }
2043
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002044 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002045 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002046 vol->iocharset = kstrdup(string,
2047 GFP_KERNEL);
2048 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002049 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002050 goto cifs_parse_mount_err;
2051 }
2052 }
2053 /* if iocharset not set then load_nls_default
2054 * is used by caller
2055 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002056 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002057 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002058 case Opt_netbiosname:
2059 string = match_strdup(args);
2060 if (string == NULL)
2061 goto out_nomem;
2062
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002063 memset(vol->source_rfc1001_name, 0x20,
2064 RFC1001_NAME_LEN);
2065 /*
2066 * FIXME: are there cases in which a comma can
2067 * be valid in workstation netbios name (and
2068 * need special handling)?
2069 */
2070 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2071 /* don't ucase netbiosname for user */
2072 if (string[i] == 0)
2073 break;
2074 vol->source_rfc1001_name[i] = string[i];
2075 }
2076 /* The string has 16th byte zero still from
2077 * set at top of the function
2078 */
2079 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002080 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002081 break;
2082 case Opt_servern:
2083 /* servernetbiosname specified override *SMBSERVER */
2084 string = match_strdup(args);
2085 if (string == NULL)
2086 goto out_nomem;
2087
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002088 /* last byte, type, is 0x20 for servr type */
2089 memset(vol->target_rfc1001_name, 0x20,
2090 RFC1001_NAME_LEN_WITH_NULL);
2091
2092 /* BB are there cases in which a comma can be
2093 valid in this workstation netbios name
2094 (and need special handling)? */
2095
2096 /* user or mount helper must uppercase the
2097 netbios name */
2098 for (i = 0; i < 15; i++) {
2099 if (string[i] == 0)
2100 break;
2101 vol->target_rfc1001_name[i] = string[i];
2102 }
2103 /* The string has 16th byte zero still from
2104 set at top of the function */
2105 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002106 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002107 break;
2108 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002109 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002110 string = match_strdup(args);
2111 if (string == NULL)
2112 goto out_nomem;
2113
Steve French7e682f72017-08-31 21:34:24 -05002114 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002115 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002116 if (strlen(string) > 1) {
2117 pr_warn("Bad mount helper ver=%s. Did "
2118 "you want SMB1 (CIFS) dialect "
2119 "and mean to type vers=1.0 "
2120 "instead?\n", string);
2121 goto cifs_parse_mount_err;
2122 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002123 /* This is the default */
2124 break;
2125 }
2126 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05002127 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002128 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002129 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002130 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002131 string = match_strdup(args);
2132 if (string == NULL)
2133 goto out_nomem;
2134
Steve Frenchc7c137b2018-06-06 17:59:29 -05002135 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002136 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002137 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002138 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002139 case Opt_sec:
2140 string = match_strdup(args);
2141 if (string == NULL)
2142 goto out_nomem;
2143
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002144 if (cifs_parse_security_flavors(string, vol) != 0)
2145 goto cifs_parse_mount_err;
2146 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002147 case Opt_cache:
2148 string = match_strdup(args);
2149 if (string == NULL)
2150 goto out_nomem;
2151
2152 if (cifs_parse_cache_flavor(string, vol) != 0)
2153 goto cifs_parse_mount_err;
2154 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002155 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002156 /*
2157 * An option we don't recognize. Save it off for later
2158 * if we haven't already found one
2159 */
2160 if (!invalid)
2161 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002162 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002164 /* Free up any allocated string */
2165 kfree(string);
2166 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002168
Jeff Laytond8162552012-03-23 14:40:56 -04002169 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002170 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002171 goto cifs_parse_mount_err;
2172 }
2173
Long Li8339dd32017-11-07 01:54:55 -07002174 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2175 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2176 goto cifs_parse_mount_err;
2177 }
2178
Jeff Layton8a8798a2012-01-17 16:09:15 -05002179#ifndef CONFIG_KEYS
2180 /* Muliuser mounts require CONFIG_KEYS support */
2181 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002182 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002183 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002184 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002185#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002186 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002187 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002188 goto cifs_parse_mount_err;
2189 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002190
Jeff Layton62a1a432012-12-10 06:10:45 -05002191 /* make sure UNC has a share name */
2192 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002193 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002194 goto cifs_parse_mount_err;
2195 }
2196
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002197 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002198 int len;
2199 const char *slash;
2200
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002201 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002202 /* Use the address part of the UNC. */
2203 slash = strchr(&vol->UNC[2], '\\');
2204 len = slash - &vol->UNC[2];
2205 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002206 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002207 goto cifs_parse_mount_err;
2208 }
2209 }
2210
2211 /* set the port that we got earlier */
2212 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002214 if (uid_specified)
2215 vol->override_uid = override_uid;
2216 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002217 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002218
2219 if (gid_specified)
2220 vol->override_gid = override_gid;
2221 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002222 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002223
Steve French7e682f72017-08-31 21:34:24 -05002224 if (got_version == false)
2225 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002226 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002227 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002228 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2229 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002230
Sean Finneyb9468452011-04-11 13:19:32 +00002231 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002233
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002234out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002235 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002236cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002237 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002238 kfree(mountdata_copy);
2239 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240}
2241
Ben Greear3eb9a882010-09-01 17:06:02 -07002242/** Returns true if srcaddr isn't specified and rhs isn't
2243 * specified, or if srcaddr is specified and
2244 * matches the IP address of the rhs argument.
2245 */
Jeff Layton45151482010-07-06 20:43:02 -04002246static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002247srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2248{
2249 switch (srcaddr->sa_family) {
2250 case AF_UNSPEC:
2251 return (rhs->sa_family == AF_UNSPEC);
2252 case AF_INET: {
2253 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2254 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2255 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2256 }
2257 case AF_INET6: {
2258 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002259 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002260 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2261 }
2262 default:
2263 WARN_ON(1);
2264 return false; /* don't expect to be here */
2265 }
2266}
2267
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002268/*
2269 * If no port is specified in addr structure, we try to match with 445 port
2270 * and if it fails - with 139 ports. It should be called only if address
2271 * families of server and addr are equal.
2272 */
2273static bool
2274match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2275{
Steve French6da97912011-03-13 18:55:55 +00002276 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002277
2278 switch (addr->sa_family) {
2279 case AF_INET:
2280 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2281 port = ((struct sockaddr_in *) addr)->sin_port;
2282 break;
2283 case AF_INET6:
2284 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2285 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2286 break;
2287 default:
2288 WARN_ON(1);
2289 return false;
2290 }
2291
2292 if (!port) {
2293 port = htons(CIFS_PORT);
2294 if (port == *sport)
2295 return true;
2296
2297 port = htons(RFC1001_PORT);
2298 }
2299
2300 return port == *sport;
2301}
Ben Greear3eb9a882010-09-01 17:06:02 -07002302
2303static bool
2304match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2305 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306{
Jeff Layton45151482010-07-06 20:43:02 -04002307 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002308 case AF_INET: {
2309 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2310 struct sockaddr_in *srv_addr4 =
2311 (struct sockaddr_in *)&server->dstaddr;
2312
2313 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002314 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002315 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002316 }
2317 case AF_INET6: {
2318 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2319 struct sockaddr_in6 *srv_addr6 =
2320 (struct sockaddr_in6 *)&server->dstaddr;
2321
Jeff Layton45151482010-07-06 20:43:02 -04002322 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002323 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002324 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002325 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002326 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002327 break;
2328 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002329 default:
2330 WARN_ON(1);
2331 return false; /* don't expect to be here */
2332 }
Jeff Layton45151482010-07-06 20:43:02 -04002333
Ben Greear3eb9a882010-09-01 17:06:02 -07002334 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2335 return false;
2336
Jeff Layton45151482010-07-06 20:43:02 -04002337 return true;
2338}
2339
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002340static bool
2341match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2342{
Jeff Layton3f618222013-06-12 19:52:14 -05002343 /*
2344 * The select_sectype function should either return the vol->sectype
2345 * that was specified, or "Unspecified" if that sectype was not
2346 * compatible with the given NEGOTIATE request.
2347 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302348 if (server->ops->select_sectype(server, vol->sectype)
2349 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002350 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002351
Jeff Layton3f618222013-06-12 19:52:14 -05002352 /*
2353 * Now check if signing mode is acceptable. No need to check
2354 * global_secflags at this point since if MUST_SIGN is set then
2355 * the server->sign had better be too.
2356 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002357 if (vol->sign && !server->sign)
2358 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002359
2360 return true;
2361}
2362
Jeff Layton9fa114f2012-11-26 11:09:57 -05002363static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002364{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002365 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2366
Jeff Laytona0b3df52013-05-24 07:40:59 -04002367 if (vol->nosharesock)
2368 return 0;
2369
Steve French9764c022017-09-17 10:41:35 -05002370 /* BB update this for smb3any and default case */
Jeff Layton23db65f2012-05-15 12:20:51 -04002371 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2372 return 0;
2373
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002374 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2375 return 0;
2376
2377 if (!match_address(server, addr,
2378 (struct sockaddr *)&vol->srcaddr))
2379 return 0;
2380
2381 if (!match_port(server, addr))
2382 return 0;
2383
2384 if (!match_security(server, vol))
2385 return 0;
2386
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002387 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002388 return 0;
2389
Long Li8339dd32017-11-07 01:54:55 -07002390 if (server->rdma != vol->rdma)
2391 return 0;
2392
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002393 return 1;
2394}
2395
Jeff Layton45151482010-07-06 20:43:02 -04002396static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002397cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002398{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002399 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302401 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002402 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002403 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002404 continue;
2405
Jeff Laytone7ddee92008-11-14 13:44:38 -05002406 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302407 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002408 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002409 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302411 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 return NULL;
2413}
2414
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002415void
2416cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002418 struct task_struct *task;
2419
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302420 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002421 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302422 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002423 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002425
Rob Landleyf1d0c992011-01-22 15:44:05 -06002426 put_net(cifs_net_ns(server));
2427
Jeff Laytone7ddee92008-11-14 13:44:38 -05002428 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302429 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002430
Jeff Laytonc74093b2011-01-11 07:24:23 -05002431 cancel_delayed_work_sync(&server->echo);
2432
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002433 if (from_reconnect)
2434 /*
2435 * Avoid deadlock here: reconnect work calls
2436 * cifs_put_tcp_session() at its end. Need to be sure
2437 * that reconnect work does nothing with server pointer after
2438 * that step.
2439 */
2440 cancel_delayed_work(&server->reconnect);
2441 else
2442 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002443
Jeff Laytone7ddee92008-11-14 13:44:38 -05002444 spin_lock(&GlobalMid_Lock);
2445 server->tcpStatus = CifsExiting;
2446 spin_unlock(&GlobalMid_Lock);
2447
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002448 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302449 cifs_fscache_release_client_cookie(server);
2450
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002451 kfree(server->session_key.response);
2452 server->session_key.response = NULL;
2453 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002454
2455 task = xchg(&server->tsk, NULL);
2456 if (task)
Eric W. Biedermane6a13c72019-05-15 12:33:50 -05002457 send_sig(SIGKILL, task, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458}
2459
Jeff Layton63c038c2008-12-01 18:41:46 -05002460static struct TCP_Server_Info *
2461cifs_get_tcp_session(struct smb_vol *volume_info)
2462{
2463 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002464 int rc;
2465
Joe Perchesf96637b2013-05-04 22:12:25 -05002466 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002467
2468 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002469 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002470 if (tcp_ses)
2471 return tcp_ses;
2472
2473 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2474 if (!tcp_ses) {
2475 rc = -ENOMEM;
2476 goto out_err;
2477 }
2478
Jeff Layton23db65f2012-05-15 12:20:51 -04002479 tcp_ses->ops = volume_info->ops;
2480 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002481 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002482 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2483 if (IS_ERR(tcp_ses->hostname)) {
2484 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002485 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002486 }
2487
2488 tcp_ses->noblocksnd = volume_info->noblocksnd;
2489 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002490 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002491 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002492 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002493 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002494 init_waitqueue_head(&tcp_ses->response_q);
2495 init_waitqueue_head(&tcp_ses->request_q);
2496 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2497 mutex_init(&tcp_ses->srv_mutex);
2498 memcpy(tcp_ses->workstation_RFC1001_name,
2499 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2500 memcpy(tcp_ses->server_RFC1001_name,
2501 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002502 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002503 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002504 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002505 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002506 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2507 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002508 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002509 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2510 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002511 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2512 sizeof(tcp_ses->srcaddr));
2513 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2514 sizeof(tcp_ses->dstaddr));
Steve Frenchfa70b872016-09-22 00:39:34 -05002515 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002516 /*
2517 * at this point we are the only ones with the pointer
2518 * to the struct since the kernel thread not created yet
2519 * no need to spinlock this init of tcpStatus or srv_count
2520 */
2521 tcp_ses->tcpStatus = CifsNew;
2522 ++tcp_ses->srv_count;
2523
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002524 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2525 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2526 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2527 else
2528 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002529 if (tcp_ses->rdma) {
2530#ifndef CONFIG_CIFS_SMB_DIRECT
2531 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2532 rc = -ENOENT;
2533 goto out_err_crypto_release;
2534#endif
2535 tcp_ses->smbd_conn = smbd_get_connection(
2536 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2537 if (tcp_ses->smbd_conn) {
2538 cifs_dbg(VFS, "RDMA transport established\n");
2539 rc = 0;
2540 goto smbd_connected;
2541 } else {
2542 rc = -ENOENT;
2543 goto out_err_crypto_release;
2544 }
2545 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002546 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002547 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002548 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002549 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002550 }
Long Li2f894642017-11-22 17:38:34 -07002551smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002552 /*
2553 * since we're in a cifs function already, we know that
2554 * this will succeed. No need for try_module_get().
2555 */
2556 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002557 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002558 tcp_ses, "cifsd");
2559 if (IS_ERR(tcp_ses->tsk)) {
2560 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002561 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002562 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002563 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002564 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002565 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002566
2567 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302568 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002569 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302570 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002571
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302572 cifs_fscache_get_client_cookie(tcp_ses);
2573
Jeff Laytonc74093b2011-01-11 07:24:23 -05002574 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002575 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002576
Jeff Layton63c038c2008-12-01 18:41:46 -05002577 return tcp_ses;
2578
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002579out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002580 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002581
Rob Landleyf1d0c992011-01-22 15:44:05 -06002582 put_net(cifs_net_ns(tcp_ses));
2583
Jeff Layton63c038c2008-12-01 18:41:46 -05002584out_err:
2585 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002586 if (!IS_ERR(tcp_ses->hostname))
2587 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002588 if (tcp_ses->ssocket)
2589 sock_release(tcp_ses->ssocket);
2590 kfree(tcp_ses);
2591 }
2592 return ERR_PTR(rc);
2593}
2594
Steve French96daf2b2011-05-27 04:34:02 +00002595static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002596{
Jeff Layton3f618222013-06-12 19:52:14 -05002597 if (vol->sectype != Unspecified &&
2598 vol->sectype != ses->sectype)
2599 return 0;
2600
2601 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002602 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002603 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002604 return 0;
2605 break;
2606 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002607 /* NULL username means anonymous session */
2608 if (ses->user_name == NULL) {
2609 if (!vol->nullauth)
2610 return 0;
2611 break;
2612 }
2613
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002614 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002615 if (strncmp(ses->user_name,
2616 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002617 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002618 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002619 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002620 ses->password != NULL &&
2621 strncmp(ses->password,
2622 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002623 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002624 return 0;
2625 }
2626 return 1;
2627}
2628
Aurelien Aptelb327a712018-01-24 13:46:10 +01002629/**
2630 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2631 *
2632 * A new IPC connection is made and stored in the session
2633 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2634 */
2635static int
2636cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2637{
2638 int rc = 0, xid;
2639 struct cifs_tcon *tcon;
2640 struct nls_table *nls_codepage;
2641 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2642 bool seal = false;
2643
2644 /*
2645 * If the mount request that resulted in the creation of the
2646 * session requires encryption, force IPC to be encrypted too.
2647 */
2648 if (volume_info->seal) {
2649 if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
2650 seal = true;
2651 else {
2652 cifs_dbg(VFS,
2653 "IPC: server doesn't support encryption\n");
2654 return -EOPNOTSUPP;
2655 }
2656 }
2657
2658 tcon = tconInfoAlloc();
2659 if (tcon == NULL)
2660 return -ENOMEM;
2661
Thomas Werschlein395a2072018-08-30 18:29:20 +02002662 snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002663
2664 /* cannot fail */
2665 nls_codepage = load_nls_default();
2666
2667 xid = get_xid();
2668 tcon->ses = ses;
2669 tcon->ipc = true;
2670 tcon->seal = seal;
2671 rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
2672 free_xid(xid);
2673
2674 if (rc) {
2675 cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
2676 tconInfoFree(tcon);
2677 goto out;
2678 }
2679
2680 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2681
2682 ses->tcon_ipc = tcon;
2683out:
2684 unload_nls(nls_codepage);
2685 return rc;
2686}
2687
2688/**
2689 * cifs_free_ipc - helper to release the session IPC tcon
2690 *
2691 * Needs to be called everytime a session is destroyed
2692 */
2693static int
2694cifs_free_ipc(struct cifs_ses *ses)
2695{
2696 int rc = 0, xid;
2697 struct cifs_tcon *tcon = ses->tcon_ipc;
2698
2699 if (tcon == NULL)
2700 return 0;
2701
2702 if (ses->server->ops->tree_disconnect) {
2703 xid = get_xid();
2704 rc = ses->server->ops->tree_disconnect(xid, tcon);
2705 free_xid(xid);
2706 }
2707
2708 if (rc)
2709 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
2710
2711 tconInfoFree(tcon);
2712 ses->tcon_ipc = NULL;
2713 return rc;
2714}
2715
Steve French96daf2b2011-05-27 04:34:02 +00002716static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002717cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718{
Steve French96daf2b2011-05-27 04:34:02 +00002719 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302721 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002722 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002723 if (ses->status == CifsExiting)
2724 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002725 if (!match_session(ses, vol))
2726 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002727 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302728 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002729 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302731 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 return NULL;
2733}
2734
Jeff Layton14fbf502008-11-14 13:53:46 -05002735static void
Steve French96daf2b2011-05-27 04:34:02 +00002736cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002737{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002738 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002739 struct TCP_Server_Info *server = ses->server;
2740
Joe Perchesf96637b2013-05-04 22:12:25 -05002741 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002742
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302743 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002744 if (ses->status == CifsExiting) {
2745 spin_unlock(&cifs_tcp_ses_lock);
2746 return;
2747 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002748 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302749 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002750 return;
2751 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002752 if (ses->status == CifsGood)
2753 ses->status = CifsExiting;
2754 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002755
Aurelien Aptelb327a712018-01-24 13:46:10 +01002756 cifs_free_ipc(ses);
2757
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002758 if (ses->status == CifsExiting && server->ops->logoff) {
2759 xid = get_xid();
2760 rc = server->ops->logoff(xid, ses);
2761 if (rc)
2762 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2763 __func__, rc);
2764 _free_xid(xid);
2765 }
2766
2767 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002768 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302769 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002770
Jeff Layton14fbf502008-11-14 13:53:46 -05002771 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002772 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05002773}
2774
Jeff Layton8a8798a2012-01-17 16:09:15 -05002775#ifdef CONFIG_KEYS
2776
Chen Gang057d6332013-07-19 09:01:36 +08002777/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2778#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002779
2780/* Populate username and pw fields from keyring if possible */
2781static int
2782cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2783{
2784 int rc = 0;
Ronnie Sahlberg325fa2a2019-08-22 08:09:50 +10002785 int is_domain = 0;
David Howells146aa8b2015-10-21 14:04:48 +01002786 const char *delim, *payload;
2787 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002788 ssize_t len;
2789 struct key *key;
2790 struct TCP_Server_Info *server = ses->server;
2791 struct sockaddr_in *sa;
2792 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01002793 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002794
2795 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2796 if (!desc)
2797 return -ENOMEM;
2798
2799 /* try to find an address key first */
2800 switch (server->dstaddr.ss_family) {
2801 case AF_INET:
2802 sa = (struct sockaddr_in *)&server->dstaddr;
2803 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2804 break;
2805 case AF_INET6:
2806 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2807 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2808 break;
2809 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002810 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2811 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002812 rc = -EINVAL;
2813 goto out_err;
2814 }
2815
Joe Perchesf96637b2013-05-04 22:12:25 -05002816 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002817 key = request_key(&key_type_logon, desc, "");
2818 if (IS_ERR(key)) {
2819 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002820 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002821 rc = PTR_ERR(key);
2822 goto out_err;
2823 }
2824
2825 /* didn't work, try to find a domain key */
2826 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002827 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002828 key = request_key(&key_type_logon, desc, "");
2829 if (IS_ERR(key)) {
2830 rc = PTR_ERR(key);
2831 goto out_err;
2832 }
Ronnie Sahlberg325fa2a2019-08-22 08:09:50 +10002833 is_domain = 1;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002834 }
2835
2836 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00002837 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002838 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002839 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002840 goto out_key_put;
2841 }
2842
2843 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01002844 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002845 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002846 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002847 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002848 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2849 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002850 rc = -EINVAL;
2851 goto out_key_put;
2852 }
2853
2854 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002855 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002856 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2857 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002858 rc = -EINVAL;
2859 goto out_key_put;
2860 }
2861
2862 vol->username = kstrndup(payload, len, GFP_KERNEL);
2863 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002864 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2865 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002866 rc = -ENOMEM;
2867 goto out_key_put;
2868 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002869 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002870
2871 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002872 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002873 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002874 rc = -EINVAL;
2875 kfree(vol->username);
2876 vol->username = NULL;
2877 goto out_key_put;
2878 }
2879
2880 ++delim;
2881 vol->password = kstrndup(delim, len, GFP_KERNEL);
2882 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002883 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2884 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002885 rc = -ENOMEM;
2886 kfree(vol->username);
2887 vol->username = NULL;
2888 goto out_key_put;
2889 }
2890
Ronnie Sahlberg325fa2a2019-08-22 08:09:50 +10002891 /*
2892 * If we have a domain key then we must set the domainName in the
2893 * for the request.
2894 */
2895 if (is_domain && ses->domainName) {
2896 vol->domainname = kstrndup(ses->domainName,
2897 strlen(ses->domainName),
2898 GFP_KERNEL);
2899 if (!vol->domainname) {
2900 cifs_dbg(FYI, "Unable to allocate %zd bytes for "
2901 "domain\n", len);
2902 rc = -ENOMEM;
2903 kfree(vol->username);
2904 vol->username = NULL;
Dan Carpenterb6294682019-08-27 13:59:17 +03002905 kzfree(vol->password);
Ronnie Sahlberg325fa2a2019-08-22 08:09:50 +10002906 vol->password = NULL;
2907 goto out_key_put;
2908 }
2909 }
2910
Jeff Layton8a8798a2012-01-17 16:09:15 -05002911out_key_put:
2912 up_read(&key->sem);
2913 key_put(key);
2914out_err:
2915 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002916 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002917 return rc;
2918}
2919#else /* ! CONFIG_KEYS */
2920static inline int
2921cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2922 struct cifs_ses *ses __attribute__((unused)))
2923{
2924 return -ENOSYS;
2925}
2926#endif /* CONFIG_KEYS */
2927
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002928/**
2929 * cifs_get_smb_ses - get a session matching @volume_info data from @server
2930 *
2931 * This function assumes it is being called from cifs_mount() where we
2932 * already got a server reference (server refcount +1). See
2933 * cifs_get_tcon() for refcount explanations.
2934 */
Steve French96daf2b2011-05-27 04:34:02 +00002935static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002936cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2937{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002938 int rc = -ENOMEM;
2939 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002940 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002941 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2942 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002943
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002944 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002945
Jeff Layton4ff67b72010-07-06 20:43:02 -04002946 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002947 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002948 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2949 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002950
Jeff Layton36988c72010-04-24 07:57:43 -04002951 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002952 rc = cifs_negotiate_protocol(xid, ses);
2953 if (rc) {
2954 mutex_unlock(&ses->session_mutex);
2955 /* problem -- put our ses reference */
2956 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002957 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002958 return ERR_PTR(rc);
2959 }
Jeff Layton36988c72010-04-24 07:57:43 -04002960 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002961 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002962 rc = cifs_setup_session(xid, ses,
2963 volume_info->local_nls);
2964 if (rc) {
2965 mutex_unlock(&ses->session_mutex);
2966 /* problem -- put our reference */
2967 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002968 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002969 return ERR_PTR(rc);
2970 }
2971 }
2972 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002973
2974 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002975 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002976 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002977 return ses;
2978 }
2979
Joe Perchesf96637b2013-05-04 22:12:25 -05002980 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002981 ses = sesInfoAlloc();
2982 if (ses == NULL)
2983 goto get_ses_fail;
2984
2985 /* new SMB session uses our server ref */
2986 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002987 if (server->dstaddr.ss_family == AF_INET6)
2988 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002989 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002990 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002991
Steve French8727c8a2011-02-25 01:11:56 -06002992 if (volume_info->username) {
2993 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2994 if (!ses->user_name)
2995 goto get_ses_fail;
2996 }
Jeff Layton36988c72010-04-24 07:57:43 -04002997
2998 /* volume_info->password freed at unmount */
2999 if (volume_info->password) {
3000 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3001 if (!ses->password)
3002 goto get_ses_fail;
3003 }
3004 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003005 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3006 if (!ses->domainName)
3007 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003008 }
Germano Percossi39566442016-12-15 12:31:18 +05303009 if (volume_info->domainauto)
3010 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003011 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003012 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003013
Jeff Layton28e11bd2013-05-26 07:01:00 -04003014 ses->sectype = volume_info->sectype;
3015 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003016
3017 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003018 rc = cifs_negotiate_protocol(xid, ses);
3019 if (!rc)
3020 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04003021 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003022 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003023 goto get_ses_fail;
3024
3025 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303026 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003027 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303028 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003029
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003030 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003031
3032 cifs_setup_ipc(ses, volume_info);
3033
Jeff Layton36988c72010-04-24 07:57:43 -04003034 return ses;
3035
3036get_ses_fail:
3037 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003038 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003039 return ERR_PTR(rc);
3040}
3041
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003042static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003043{
3044 if (tcon->tidStatus == CifsExiting)
3045 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003046 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003047 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003048 if (tcon->seal != volume_info->seal)
3049 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003050 if (tcon->snapshot_time != volume_info->snapshot_time)
3051 return 0;
Steve French2e96c932019-09-11 21:46:20 -05003052 if (tcon->no_lease != volume_info->no_lease)
3053 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003054 return 1;
3055}
3056
Steve French96daf2b2011-05-27 04:34:02 +00003057static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003058cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059{
3060 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003061 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303063 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003064 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003065 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003066 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003067 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003068 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303069 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 return tcon;
3071 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303072 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 return NULL;
3074}
3075
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003076void
Steve French96daf2b2011-05-27 04:34:02 +00003077cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003078{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003079 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003080 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003081
Aurelien Aptelb327a712018-01-24 13:46:10 +01003082 /*
3083 * IPC tcon share the lifetime of their session and are
3084 * destroyed in the session put function
3085 */
3086 if (tcon == NULL || tcon->ipc)
3087 return;
3088
3089 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003090 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303091 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003092 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303093 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003094 return;
3095 }
3096
3097 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303098 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003099
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003100 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003101 if (ses->server->ops->tree_disconnect)
3102 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003103 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003104
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303105 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003106 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003107 cifs_put_smb_ses(ses);
3108}
3109
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003110/**
3111 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3112 *
3113 * - tcon refcount is the number of mount points using the tcon.
3114 * - ses refcount is the number of tcon using the session.
3115 *
3116 * 1. This function assumes it is being called from cifs_mount() where
3117 * we already got a session reference (ses refcount +1).
3118 *
3119 * 2. Since we're in the context of adding a mount point, the end
3120 * result should be either:
3121 *
3122 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3123 * its session refcount incremented (1 new tcon). This +1 was
3124 * already done in (1).
3125 *
3126 * b) an existing tcon with refcount+1 (add a mount point to it) and
3127 * identical ses refcount (no new tcon). Because of (1) we need to
3128 * decrement the ses refcount.
3129 */
Steve French96daf2b2011-05-27 04:34:02 +00003130static struct cifs_tcon *
3131cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003132{
3133 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003134 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003135
Steve French8b217fe2016-11-11 22:36:20 -06003136 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003137 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003138 /*
3139 * tcon has refcount already incremented but we need to
3140 * decrement extra ses reference gotten by caller (case b)
3141 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003142 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003143 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003144 return tcon;
3145 }
3146
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003147 if (!ses->server->ops->tree_connect) {
3148 rc = -ENOSYS;
3149 goto out_fail;
3150 }
3151
Jeff Laytond00c28d2010-04-24 07:57:44 -04003152 tcon = tconInfoAlloc();
3153 if (tcon == NULL) {
3154 rc = -ENOMEM;
3155 goto out_fail;
3156 }
3157
Steve French8b217fe2016-11-11 22:36:20 -06003158 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003159 if (ses->server->vals->protocol_id == 0) {
3160 cifs_dbg(VFS,
3161 "Use SMB2 or later for snapshot mount option\n");
3162 rc = -EOPNOTSUPP;
3163 goto out_fail;
3164 } else
3165 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003166 }
3167
Jeff Laytond00c28d2010-04-24 07:57:44 -04003168 tcon->ses = ses;
3169 if (volume_info->password) {
3170 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3171 if (!tcon->password) {
3172 rc = -ENOMEM;
3173 goto out_fail;
3174 }
3175 }
3176
Steve French23657ad2018-04-22 15:14:58 -05003177 if (volume_info->seal) {
3178 if (ses->server->vals->protocol_id == 0) {
3179 cifs_dbg(VFS,
3180 "SMB3 or later required for encryption\n");
3181 rc = -EOPNOTSUPP;
3182 goto out_fail;
3183 } else if (tcon->ses->server->capabilities &
3184 SMB2_GLOBAL_CAP_ENCRYPTION)
3185 tcon->seal = true;
3186 else {
3187 cifs_dbg(VFS, "Encryption is not supported on share\n");
3188 rc = -EOPNOTSUPP;
3189 goto out_fail;
3190 }
3191 }
3192
Steve French8505c8b2018-06-18 14:01:59 -05003193 if (volume_info->linux_ext) {
3194 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003195 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003196 printk_once(KERN_WARNING
3197 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003198 } else {
3199 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3200 rc = -EOPNOTSUPP;
3201 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003202 }
Steve Frenchb3266142018-05-20 23:41:10 -05003203 }
Steve Frenchb3266142018-05-20 23:41:10 -05003204
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003205 /*
3206 * BB Do we need to wrap session_mutex around this TCon call and Unix
3207 * SetFS as we do on SessSetup and reconnect?
3208 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003209 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003210 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3211 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003212 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003213 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003214 if (rc)
3215 goto out_fail;
3216
3217 if (volume_info->nodfs) {
3218 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05003219 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003220 }
Steve Frenchb618f002015-11-03 09:15:03 -06003221 tcon->use_persistent = false;
3222 /* check if SMB2 or later, CIFS does not support persistent handles */
3223 if (volume_info->persistent) {
3224 if (ses->server->vals->protocol_id == 0) {
3225 cifs_dbg(VFS,
3226 "SMB3 or later required for persistent handles\n");
3227 rc = -EOPNOTSUPP;
3228 goto out_fail;
3229 } else if (ses->server->capabilities &
3230 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3231 tcon->use_persistent = true;
3232 else /* persistent handles requested but not supported */ {
3233 cifs_dbg(VFS,
3234 "Persistent handles not supported on share\n");
3235 rc = -EOPNOTSUPP;
3236 goto out_fail;
3237 }
3238 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3239 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3240 && (volume_info->nopersistent == false)) {
3241 cifs_dbg(FYI, "enabling persistent handles\n");
3242 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003243 } else if (volume_info->resilient) {
3244 if (ses->server->vals->protocol_id == 0) {
3245 cifs_dbg(VFS,
3246 "SMB2.1 or later required for resilient handles\n");
3247 rc = -EOPNOTSUPP;
3248 goto out_fail;
3249 }
3250 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003251 }
3252
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003253 /*
3254 * We can have only one retry value for a connection to a share so for
3255 * resources mounted more than once to the same server share the last
3256 * value passed in for the retry flag is used.
3257 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003258 tcon->retry = volume_info->retry;
3259 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003260 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003261 tcon->local_lease = volume_info->local_lease;
Steve French2e96c932019-09-11 21:46:20 -05003262 tcon->no_lease = volume_info->no_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003263 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003264
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303265 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003266 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303267 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003268
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303269 cifs_fscache_get_super_cookie(tcon);
3270
Jeff Laytond00c28d2010-04-24 07:57:44 -04003271 return tcon;
3272
3273out_fail:
3274 tconInfoFree(tcon);
3275 return ERR_PTR(rc);
3276}
3277
Jeff Layton9d002df2010-10-06 19:51:11 -04003278void
3279cifs_put_tlink(struct tcon_link *tlink)
3280{
3281 if (!tlink || IS_ERR(tlink))
3282 return;
3283
3284 if (!atomic_dec_and_test(&tlink->tl_count) ||
3285 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3286 tlink->tl_time = jiffies;
3287 return;
3288 }
3289
3290 if (!IS_ERR(tlink_tcon(tlink)))
3291 cifs_put_tcon(tlink_tcon(tlink));
3292 kfree(tlink);
3293 return;
3294}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003295
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003296static int
3297compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3298{
3299 struct cifs_sb_info *old = CIFS_SB(sb);
3300 struct cifs_sb_info *new = mnt_data->cifs_sb;
Paulo Alcantara (SUSE)987564c2019-06-18 16:16:02 -03003301 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3302 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003303
3304 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3305 return 0;
3306
Paulo Alcantara (SUSE)987564c2019-06-18 16:16:02 -03003307 if (old->mnt_cifs_serverino_autodisabled)
3308 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3309
3310 if (oldflags != newflags)
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003311 return 0;
3312
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003313 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003314 * We want to share sb only if we don't specify an r/wsize or
3315 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003316 */
3317 if (new->wsize && new->wsize < old->wsize)
3318 return 0;
3319
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003320 if (new->rsize && new->rsize < old->rsize)
3321 return 0;
3322
Eric W. Biederman1f682332013-02-06 01:20:20 -08003323 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003324 return 0;
3325
3326 if (old->mnt_file_mode != new->mnt_file_mode ||
3327 old->mnt_dir_mode != new->mnt_dir_mode)
3328 return 0;
3329
3330 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3331 return 0;
3332
3333 if (old->actimeo != new->actimeo)
3334 return 0;
3335
3336 return 1;
3337}
3338
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003339static int
3340match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3341{
3342 struct cifs_sb_info *old = CIFS_SB(sb);
3343 struct cifs_sb_info *new = mnt_data->cifs_sb;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003344 bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3345 bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003346
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003347 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003348 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003349 else if (!old_set && !new_set)
3350 return 1;
3351
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003352 return 0;
3353}
3354
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003355int
3356cifs_match_super(struct super_block *sb, void *data)
3357{
3358 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3359 struct smb_vol *volume_info;
3360 struct cifs_sb_info *cifs_sb;
3361 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003362 struct cifs_ses *ses;
3363 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003364 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003365 int rc = 0;
3366
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003367 spin_lock(&cifs_tcp_ses_lock);
3368 cifs_sb = CIFS_SB(sb);
3369 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3370 if (IS_ERR(tlink)) {
3371 spin_unlock(&cifs_tcp_ses_lock);
3372 return rc;
3373 }
3374 tcon = tlink_tcon(tlink);
3375 ses = tcon->ses;
3376 tcp_srv = ses->server;
3377
3378 volume_info = mnt_data->vol;
3379
Jeff Layton9fa114f2012-11-26 11:09:57 -05003380 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003381 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003382 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003383 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003384 rc = 0;
3385 goto out;
3386 }
3387
3388 rc = compare_mount_options(sb, mnt_data);
3389out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003390 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003391 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003392 return rc;
3393}
3394
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003396get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003397 const struct nls_table *nls_codepage, unsigned int *num_referrals,
3398 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400 int rc = 0;
3401
Aurelien Aptelb327a712018-01-24 13:46:10 +01003402 if (!ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003403 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003405 *num_referrals = 0;
3406 *referrals = NULL;
3407
Aurelien Aptelb327a712018-01-24 13:46:10 +01003408 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
3409 referrals, num_referrals,
3410 nls_codepage, remap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 return rc;
3412}
3413
Jeff Layton09e50d52008-07-23 10:11:19 -04003414#ifdef CONFIG_DEBUG_LOCK_ALLOC
3415static struct lock_class_key cifs_key[2];
3416static struct lock_class_key cifs_slock_key[2];
3417
3418static inline void
3419cifs_reclassify_socket4(struct socket *sock)
3420{
3421 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003422 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003423 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3424 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3425}
3426
3427static inline void
3428cifs_reclassify_socket6(struct socket *sock)
3429{
3430 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003431 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003432 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3433 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3434}
3435#else
3436static inline void
3437cifs_reclassify_socket4(struct socket *sock)
3438{
3439}
3440
3441static inline void
3442cifs_reclassify_socket6(struct socket *sock)
3443{
3444}
3445#endif
3446
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003448static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449{
Steve French50c2f752007-07-13 00:33:32 +00003450 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451
Steve French50c2f752007-07-13 00:33:32 +00003452 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 /* mask a nibble at a time and encode */
3454 target[j] = 'A' + (0x0F & (source[i] >> 4));
3455 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003456 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 }
3458
3459}
3460
Ben Greear3eb9a882010-09-01 17:06:02 -07003461static int
3462bind_socket(struct TCP_Server_Info *server)
3463{
3464 int rc = 0;
3465 if (server->srcaddr.ss_family != AF_UNSPEC) {
3466 /* Bind to the specified local IP address */
3467 struct socket *socket = server->ssocket;
3468 rc = socket->ops->bind(socket,
3469 (struct sockaddr *) &server->srcaddr,
3470 sizeof(server->srcaddr));
3471 if (rc < 0) {
3472 struct sockaddr_in *saddr4;
3473 struct sockaddr_in6 *saddr6;
3474 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3475 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3476 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05003477 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3478 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003479 else
Joe Perchesf96637b2013-05-04 22:12:25 -05003480 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3481 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003482 }
3483 }
3484 return rc;
3485}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486
3487static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003488ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489{
3490 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003491 /*
3492 * some servers require RFC1001 sessinit before sending
3493 * negprot - BB check reconnection in case where second
3494 * sessinit is sent but no second negprot
3495 */
3496 struct rfc1002_session_packet *ses_init_buf;
3497 struct smb_hdr *smb_buf;
3498 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3499 GFP_KERNEL);
3500 if (ses_init_buf) {
3501 ses_init_buf->trailer.session_req.called_len = 32;
3502
Colin Ian King997152f2016-01-25 16:25:54 +00003503 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003504 rfc1002mangle(ses_init_buf->trailer.
3505 session_req.called_name,
3506 server->server_RFC1001_name,
3507 RFC1001_NAME_LEN_WITH_NULL);
3508 else
3509 rfc1002mangle(ses_init_buf->trailer.
3510 session_req.called_name,
3511 DEFAULT_CIFS_CALLED_NAME,
3512 RFC1001_NAME_LEN_WITH_NULL);
3513
3514 ses_init_buf->trailer.session_req.calling_len = 32;
3515
3516 /*
3517 * calling name ends in null (byte 16) from old smb
3518 * convention.
3519 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003520 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003521 rfc1002mangle(ses_init_buf->trailer.
3522 session_req.calling_name,
3523 server->workstation_RFC1001_name,
3524 RFC1001_NAME_LEN_WITH_NULL);
3525 else
3526 rfc1002mangle(ses_init_buf->trailer.
3527 session_req.calling_name,
3528 "LINUX_CIFS_CLNT",
3529 RFC1001_NAME_LEN_WITH_NULL);
3530
3531 ses_init_buf->trailer.session_req.scope1 = 0;
3532 ses_init_buf->trailer.session_req.scope2 = 0;
3533 smb_buf = (struct smb_hdr *)ses_init_buf;
3534
3535 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003536 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003537 rc = smb_send(server, smb_buf, 0x44);
3538 kfree(ses_init_buf);
3539 /*
3540 * RFC1001 layer in at least one server
3541 * requires very short break before negprot
3542 * presumably because not expecting negprot
3543 * to follow so fast. This is a simple
3544 * solution that works without
3545 * complicating the code and causes no
3546 * significant slowing down on mount
3547 * for everyone else
3548 */
3549 usleep_range(1000, 2000);
3550 }
3551 /*
3552 * else the negprot may still work without this
3553 * even though malloc failed
3554 */
3555
3556 return rc;
3557}
3558
3559static int
3560generic_ip_connect(struct TCP_Server_Info *server)
3561{
3562 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003563 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003564 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003565 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003566 struct sockaddr *saddr;
3567
3568 saddr = (struct sockaddr *) &server->dstaddr;
3569
3570 if (server->dstaddr.ss_family == AF_INET6) {
3571 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3572 slen = sizeof(struct sockaddr_in6);
3573 sfamily = AF_INET6;
3574 } else {
3575 sport = ((struct sockaddr_in *) saddr)->sin_port;
3576 slen = sizeof(struct sockaddr_in);
3577 sfamily = AF_INET;
3578 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003580 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003581 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3582 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003584 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003585 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003588
3589 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003590 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003591 server->ssocket = socket;
3592 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003593 if (sfamily == AF_INET6)
3594 cifs_reclassify_socket6(socket);
3595 else
3596 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 }
3598
Ben Greear3eb9a882010-09-01 17:06:02 -07003599 rc = bind_socket(server);
3600 if (rc < 0)
3601 return rc;
3602
Jeff Laytond5c56052008-12-01 18:42:33 -05003603 /*
3604 * Eventually check for other socket options to change from
3605 * the default. sock_setsockopt not used because it expects
3606 * user space buffer
3607 */
3608 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003609 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003610
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003611 /* make the bufsizes depend on wsize/rsize and max requests */
3612 if (server->noautotune) {
3613 if (socket->sk->sk_sndbuf < (200 * 1024))
3614 socket->sk->sk_sndbuf = 200 * 1024;
3615 if (socket->sk->sk_rcvbuf < (140 * 1024))
3616 socket->sk->sk_rcvbuf = 140 * 1024;
3617 }
3618
Steve French6a5fa2362010-01-01 01:28:43 +00003619 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003620 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003621 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3622 (char *)&val, sizeof(val));
3623 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003624 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3625 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003626 }
3627
Joe Perchesf96637b2013-05-04 22:12:25 -05003628 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003629 socket->sk->sk_sndbuf,
3630 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3631
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003632 rc = socket->ops->connect(socket, saddr, slen, 0);
3633 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003634 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003635 sock_release(socket);
3636 server->ssocket = NULL;
3637 return rc;
3638 }
3639
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003640 if (sport == htons(RFC1001_PORT))
3641 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003642
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 return rc;
3644}
3645
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003646static int
3647ip_connect(struct TCP_Server_Info *server)
3648{
Steve French6da97912011-03-13 18:55:55 +00003649 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003650 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3651 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3652
3653 if (server->dstaddr.ss_family == AF_INET6)
3654 sport = &addr6->sin6_port;
3655 else
3656 sport = &addr->sin_port;
3657
3658 if (*sport == 0) {
3659 int rc;
3660
3661 /* try with 445 port at first */
3662 *sport = htons(CIFS_PORT);
3663
3664 rc = generic_ip_connect(server);
3665 if (rc >= 0)
3666 return rc;
3667
3668 /* if it failed, try with 139 port */
3669 *sport = htons(RFC1001_PORT);
3670 }
3671
3672 return generic_ip_connect(server);
3673}
3674
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003675void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003676 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003677{
3678 /* if we are reconnecting then should we check to see if
3679 * any requested capabilities changed locally e.g. via
3680 * remount but we can not do much about it here
3681 * if they have (even if we could detect it by the following)
3682 * Perhaps we could add a backpointer to array of sb from tcon
3683 * or if we change to make all sb to same share the same
3684 * sb as NFS - then we only have one backpointer to sb.
3685 * What if we wanted to mount the server share twice once with
3686 * and once without posixacls or posix paths? */
3687 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003688
Steve Frenchc18c8422007-07-18 23:21:09 +00003689 if (vol_info && vol_info->no_linux_ext) {
3690 tcon->fsUnixInfo.Capability = 0;
3691 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003692 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003693 return;
3694 } else if (vol_info)
3695 tcon->unix_ext = 1; /* Unix Extensions supported */
3696
3697 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003698 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003699 return;
3700 }
Steve French50c2f752007-07-13 00:33:32 +00003701
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003702 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003703 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003704 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003705 /* check for reconnect case in which we do not
3706 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003707 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003708 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003709 originally at mount time */
3710 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3711 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003712 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3713 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003714 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003715 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003716 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003717 cifs_dbg(VFS, "possible reconnect error\n");
3718 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003719 }
Steve French8af18972007-02-14 04:42:51 +00003720 }
Steve French50c2f752007-07-13 00:33:32 +00003721
Steve French6848b732011-05-26 18:38:54 +00003722 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003723 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003724
Steve French8af18972007-02-14 04:42:51 +00003725 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003726 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003727 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003728 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003729 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003730 if (cifs_sb)
3731 cifs_sb->mnt_cifs_flags |=
3732 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003733 }
3734
Steve French75865f8c2007-06-24 18:30:48 +00003735 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003736 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003737 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003738 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003739 if (cifs_sb)
3740 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003741 CIFS_MOUNT_POSIX_PATHS;
3742 }
Steve French50c2f752007-07-13 00:33:32 +00003743
Joe Perchesf96637b2013-05-04 22:12:25 -05003744 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003745#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003746 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003747 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003748 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003749 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003750 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003751 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003752 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003753 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003754 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003755 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003756 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003757 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003758 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003759 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003760 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003761 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003762 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003763 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003764#endif /* CIFS_DEBUG2 */
3765 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003766 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003767 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003768 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003769 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 +00003770
Steve French8af18972007-02-14 04:42:51 +00003771 }
3772 }
3773}
3774
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003775int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003776 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003777{
Jeff Layton2de970f2010-10-06 19:51:12 -04003778 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3779
Al Viro2ced6f62011-06-17 09:20:04 -04003780 spin_lock_init(&cifs_sb->tlink_tree_lock);
3781 cifs_sb->tlink_tree = RB_ROOT;
3782
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003783 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003784 * Temporarily set r/wsize for matching superblock. If we end up using
3785 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003786 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003787 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003788 cifs_sb->wsize = pvolume_info->wsize;
3789
Steve French3b795212008-11-13 19:45:32 +00003790 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3791 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3792 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3793 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003794 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3795 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003796
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303797 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003798 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303799
Steve French3b795212008-11-13 19:45:32 +00003800 if (pvolume_info->noperm)
3801 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3802 if (pvolume_info->setuids)
3803 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05003804 if (pvolume_info->setuidfromacl)
3805 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00003806 if (pvolume_info->server_ino)
3807 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3808 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003809 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3810 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003811 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3812 if (pvolume_info->no_xattr)
3813 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3814 if (pvolume_info->sfu_emul)
3815 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3816 if (pvolume_info->nobrl)
3817 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05003818 if (pvolume_info->nohandlecache)
3819 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00003820 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003821 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003822 if (pvolume_info->mand_lock)
3823 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003824 if (pvolume_info->rwpidforward)
3825 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003826 if (pvolume_info->cifs_acl)
3827 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003828 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003829 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003830 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3831 }
3832 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003833 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003834 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3835 }
Steve French3b795212008-11-13 19:45:32 +00003836 if (pvolume_info->override_uid)
3837 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3838 if (pvolume_info->override_gid)
3839 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3840 if (pvolume_info->dynperm)
3841 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303842 if (pvolume_info->fsc)
3843 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003844 if (pvolume_info->multiuser)
3845 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3846 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003847 if (pvolume_info->strict_io)
3848 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003849 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003850 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003851 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3852 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003853 if (pvolume_info->mfsymlinks) {
3854 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003855 /*
3856 * Our SFU ("Services for Unix" emulation does not allow
3857 * creating symlinks but does allow reading existing SFU
3858 * symlinks (it does allow both creating and reading SFU
3859 * style mknod and FIFOs though). When "mfsymlinks" and
3860 * "sfu" are both enabled at the same time, it allows
3861 * reading both types of symlinks, but will only create
3862 * them with mfsymlinks format. This allows better
3863 * Apple compatibility (probably better for Samba too)
3864 * while still recognizing old Windows style symlinks.
3865 */
3866 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003867 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003868 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003869 }
Steve French3b795212008-11-13 19:45:32 +00003870
3871 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003872 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003873
3874 if (pvolume_info->prepath) {
3875 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
3876 if (cifs_sb->prepath == NULL)
3877 return -ENOMEM;
3878 }
3879
3880 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003881}
3882
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003883static void
3884cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003885{
Sean Finneyb9468452011-04-11 13:19:32 +00003886 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003887 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003888 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003889 kfree(volume_info->domainname);
3890 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003891 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003892}
3893
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003894void
3895cifs_cleanup_volume_info(struct smb_vol *volume_info)
3896{
3897 if (!volume_info)
3898 return;
3899 cleanup_volume_info_contents(volume_info);
3900 kfree(volume_info);
3901}
3902
3903
Steve French2d6d5892009-04-09 00:36:44 +00003904#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003905/*
3906 * cifs_build_path_to_root returns full path to root when we do not have an
3907 * exiting connection (tcon)
3908 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003909static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003910build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003911 const struct cifs_sb_info *cifs_sb)
3912{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003913 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003914 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003915 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003916
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003917 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003918 if (full_path == NULL)
3919 return ERR_PTR(-ENOMEM);
3920
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003921 strncpy(full_path, vol->UNC, unc_len);
3922 pos = full_path + unc_len;
3923
3924 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04003925 *pos = CIFS_DIR_SEP(cifs_sb);
3926 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003927 pos += pplen;
3928 }
3929
3930 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003931 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003932 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003933 return full_path;
3934}
Sean Finneydd613942011-04-11 13:19:30 +00003935
3936/*
3937 * Perform a dfs referral query for a share and (optionally) prefix
3938 *
Sean Finney046462a2011-04-11 13:19:33 +00003939 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3940 * to a string containing updated options for the submount. Otherwise it
3941 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003942 *
3943 * Returns the rc from get_dfs_path to the caller, which can be used to
3944 * determine whether there were referrals.
3945 */
3946static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003947expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003948 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003949 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003950{
3951 int rc;
3952 unsigned int num_referrals = 0;
3953 struct dfs_info3_param *referrals = NULL;
3954 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3955
3956 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3957 if (IS_ERR(full_path))
3958 return PTR_ERR(full_path);
3959
3960 /* For DFS paths, skip the first '\' of the UNC */
3961 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3962
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003963 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05003964 &num_referrals, &referrals, cifs_remap(cifs_sb));
Sean Finneydd613942011-04-11 13:19:30 +00003965
3966 if (!rc && num_referrals > 0) {
3967 char *fake_devname = NULL;
3968
3969 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3970 full_path + 1, referrals,
3971 &fake_devname);
3972
3973 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003974
Sean Finneydd613942011-04-11 13:19:30 +00003975 if (IS_ERR(mdata)) {
3976 rc = PTR_ERR(mdata);
3977 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003978 } else {
3979 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003980 rc = cifs_setup_volume_info(volume_info, mdata,
Steve Frenchc7c137b2018-06-06 17:59:29 -05003981 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00003982 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003983 kfree(fake_devname);
3984 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003985 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003986 }
3987 kfree(full_path);
3988 return rc;
3989}
Steve French2d6d5892009-04-09 00:36:44 +00003990#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003991
Jeff Layton04db79b2011-07-06 08:10:38 -04003992static int
3993cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05003994 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003996 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003997
Steve Frenchc7c137b2018-06-06 17:59:29 -05003998 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04003999 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000
Jeff Layton7586b762008-12-01 18:41:49 -05004001 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004002 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004003 kfree(volume_info->username);
4004 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004005 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004007 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004009 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004010 /* In userspace mount helper we can get user name from alternate
4011 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004012 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 }
4014
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004016 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004017 /* load_nls_default cannot return null */
4018 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004020 volume_info->local_nls = load_nls(volume_info->iocharset);
4021 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004022 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004023 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004024 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025 }
4026 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004027
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004028 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004029}
4030
4031struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004032cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004033{
4034 int rc;
4035 struct smb_vol *volume_info;
4036
Jeff Layton6ee95422012-11-26 11:09:57 -05004037 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004038 if (!volume_info)
4039 return ERR_PTR(-ENOMEM);
4040
Steve Frenchc7c137b2018-06-06 17:59:29 -05004041 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004042 if (rc) {
4043 cifs_cleanup_volume_info(volume_info);
4044 volume_info = ERR_PTR(rc);
4045 }
4046
4047 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004048}
4049
Aurelien Aptela6b50582016-05-25 19:59:09 +02004050static int
4051cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4052 unsigned int xid,
4053 struct cifs_tcon *tcon,
4054 struct cifs_sb_info *cifs_sb,
4055 char *full_path)
4056{
4057 int rc;
4058 char *s;
4059 char sep, tmp;
4060
4061 sep = CIFS_DIR_SEP(cifs_sb);
4062 s = full_path;
4063
4064 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4065 while (rc == 0) {
4066 /* skip separators */
4067 while (*s == sep)
4068 s++;
4069 if (!*s)
4070 break;
4071 /* next separator */
4072 while (*s && *s != sep)
4073 s++;
4074
4075 /*
4076 * temporarily null-terminate the path at the end of
4077 * the current component
4078 */
4079 tmp = *s;
4080 *s = 0;
4081 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4082 full_path);
4083 *s = tmp;
4084 }
4085 return rc;
4086}
4087
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004088int
Al Viro2c6292a2011-06-17 09:05:48 -04004089cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004090{
Jeff Layton1daaae82012-03-21 06:30:40 -04004091 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004092 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004093 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00004094 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004095 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004096 char *full_path;
4097 struct tcon_link *tlink;
4098#ifdef CONFIG_CIFS_DFS_UPCALL
4099 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04004100#endif
Al Virodd854462011-06-17 08:24:42 -04004101
Jeff Layton20547492011-07-09 12:21:07 -04004102#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004103try_mount_again:
4104 /* cleanup activities if we're chasing a referral */
4105 if (referral_walks_count) {
4106 if (tcon)
4107 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004108 else if (ses)
4109 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004110
Sachin Prabhu1dfd18d2015-06-16 16:36:17 +01004111 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4112
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004113 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004114 }
4115#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04004116 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004117 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004118 ses = NULL;
4119 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004120 full_path = NULL;
4121 tlink = NULL;
4122
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004123 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124
Jeff Layton63c038c2008-12-01 18:41:46 -05004125 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004126 server = cifs_get_tcp_session(volume_info);
4127 if (IS_ERR(server)) {
4128 rc = PTR_ERR(server);
Jeff Layton63c038c2008-12-01 18:41:46 -05004129 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 }
Steve French141891f2016-09-23 00:44:16 -05004131 if ((volume_info->max_credits < 20) ||
4132 (volume_info->max_credits > 60000))
4133 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4134 else
4135 server->max_credits = volume_info->max_credits;
Jeff Layton36988c72010-04-24 07:57:43 -04004136 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004137 ses = cifs_get_smb_ses(server, volume_info);
4138 if (IS_ERR(ses)) {
4139 rc = PTR_ERR(ses);
4140 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04004141 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 }
Steve French50c2f752007-07-13 00:33:32 +00004143
Steve Frenchb618f002015-11-03 09:15:03 -06004144 if ((volume_info->persistent == true) && ((ses->server->capabilities &
4145 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
4146 cifs_dbg(VFS, "persistent handles not supported by server\n");
4147 rc = -EOPNOTSUPP;
4148 goto mount_fail_check;
4149 }
Steve French592fafe2015-11-03 10:08:53 -06004150
Jeff Laytond00c28d2010-04-24 07:57:44 -04004151 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004152 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04004153 if (IS_ERR(tcon)) {
4154 rc = PTR_ERR(tcon);
4155 tcon = NULL;
Mark Syms40920c22016-11-29 11:36:46 +00004156 if (rc == -EACCES)
4157 goto mount_fail_check;
4158
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004159 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04004160 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004161
Steve Frenchce558b02018-05-31 19:16:54 -05004162 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4163 if (tcon->posix_extensions)
4164 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve Frenchce558b02018-05-31 19:16:54 -05004165
Steve French6848b732011-05-26 18:38:54 +00004166 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004167 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00004168 /* reset of caps checks mount to see if unix extensions
4169 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04004170 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00004171 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4172 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4173 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
4174 rc = -EACCES;
4175 goto mount_fail_check;
4176 }
4177 } else
4178 tcon->unix_ext = 0; /* server does not support them */
4179
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004180 /* do not care if a following call succeed - informational */
Aurelien Aptelb327a712018-01-24 13:46:10 +01004181 if (!tcon->pipe && server->ops->qfs_tcon)
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004182 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00004183
Pavel Shilovsky24985c52012-09-18 16:20:28 -07004184 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
4185 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04004186
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004187remote_path_check:
Sean Finneyc1508ca2011-04-11 13:19:31 +00004188#ifdef CONFIG_CIFS_DFS_UPCALL
4189 /*
4190 * Perform an unconditional check for whether there are DFS
4191 * referrals for this path without prefix, to provide support
4192 * for DFS referrals from w2k8 servers which don't seem to respond
4193 * with PATH_NOT_COVERED to requests that include the prefix.
4194 * Chase the referral if found, otherwise continue normally.
4195 */
4196 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004197 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
4198 false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004199 if (!refrc) {
4200 referral_walks_count++;
4201 goto try_mount_again;
4202 }
4203 }
4204#endif
4205
Steve Frenchf87d39d2011-05-27 03:50:55 +00004206 /* check if a whole path is not remote */
Jeff Layton70945642011-03-14 13:48:08 -04004207 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004208 if (!server->ops->is_path_accessible) {
4209 rc = -ENOSYS;
4210 goto mount_fail_check;
4211 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004212 /*
4213 * cifs_build_path_to_root works only when we have a valid tcon
4214 */
Sachin Prabhu374402a2016-12-15 12:31:19 +05304215 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon,
4216 tcon->Flags & SMB_SHARE_IS_IN_DFS);
Igor Mammedove4cce942009-02-10 14:10:26 +03004217 if (full_path == NULL) {
4218 rc = -ENOMEM;
4219 goto mount_fail_check;
4220 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004221 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4222 full_path);
Jeff Layton03ceace2010-12-06 21:07:33 -05004223 if (rc != 0 && rc != -EREMOTE) {
Igor Mammedove4cce942009-02-10 14:10:26 +03004224 kfree(full_path);
4225 goto mount_fail_check;
4226 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004227
Sachin Prabhud1713562016-09-06 13:22:34 +01004228 if (rc != -EREMOTE) {
4229 rc = cifs_are_all_path_components_accessible(server,
Aurelien Aptela6b50582016-05-25 19:59:09 +02004230 xid, tcon, cifs_sb,
4231 full_path);
Sachin Prabhud1713562016-09-06 13:22:34 +01004232 if (rc != 0) {
4233 cifs_dbg(VFS, "cannot query dirs between root and final path, "
4234 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4235 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4236 rc = 0;
4237 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004238 }
Igor Mammedove4cce942009-02-10 14:10:26 +03004239 kfree(full_path);
4240 }
4241
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004242 /* get referral if needed */
4243 if (rc == -EREMOTE) {
Steve Frenchd036f502009-04-03 03:12:08 +00004244#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004245 if (referral_walks_count > MAX_NESTED_LINKS) {
4246 /*
4247 * BB: when we implement proper loop detection,
4248 * we will remove this check. But now we need it
4249 * to prevent an indefinite loop if 'DFS tree' is
4250 * misconfigured (i.e. has loops).
4251 */
4252 rc = -ELOOP;
4253 goto mount_fail_check;
4254 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004255
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004256 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04004257
Sean Finneydd613942011-04-11 13:19:30 +00004258 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004259 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004260 goto try_mount_again;
4261 }
Sean Finneydd613942011-04-11 13:19:30 +00004262 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00004263#else /* No DFS support, return error on mount */
4264 rc = -EOPNOTSUPP;
4265#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004266 }
4267
Jeff Layton9d002df2010-10-06 19:51:11 -04004268 if (rc)
4269 goto mount_fail_check;
4270
4271 /* now, hang the tcon off of the superblock */
4272 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
4273 if (tlink == NULL) {
4274 rc = -ENOMEM;
4275 goto mount_fail_check;
4276 }
4277
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004278 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004279 tlink->tl_tcon = tcon;
4280 tlink->tl_time = jiffies;
4281 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4282 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4283
Jeff Layton413e6612010-10-28 13:33:38 -04004284 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004285 spin_lock(&cifs_sb->tlink_tree_lock);
4286 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4287 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04004288
Jeff Laytonda472fc2012-03-23 14:40:53 -04004289 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004290 TLINK_IDLE_EXPIRE);
4291
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004292mount_fail_check:
4293 /* on error free sesinfo and tcon struct if needed */
4294 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004295 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03004296 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004297 if (tcon)
4298 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004299 else if (ses)
4300 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004301 else
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004302 cifs_put_tcp_session(server, 0);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004303 }
4304
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004305out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004306 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307 return rc;
4308}
4309
Jeff Layton8d1bca32011-06-11 21:17:10 -04004310/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01004311 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04004312 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04004314CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00004315 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316 const struct nls_table *nls_codepage)
4317{
4318 struct smb_hdr *smb_buffer;
4319 struct smb_hdr *smb_buffer_response;
4320 TCONX_REQ *pSMB;
4321 TCONX_RSP *pSMBr;
4322 unsigned char *bcc_ptr;
4323 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05004324 int length;
4325 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326
4327 if (ses == NULL)
4328 return -EIO;
4329
4330 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00004331 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00004333
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 smb_buffer_response = smb_buffer;
4335
4336 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
4337 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07004338
Pavel Shilovsky88257362012-05-23 14:01:59 +04004339 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340 smb_buffer->Uid = ses->Suid;
4341 pSMB = (TCONX_REQ *) smb_buffer;
4342 pSMBr = (TCONX_RSP *) smb_buffer_response;
4343
4344 pSMB->AndXCommand = 0xFF;
4345 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01004347 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08004348 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00004349 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08004350 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00004351 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08004352 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004353 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08004354 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
4355 specified as required (when that support is added to
4356 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00004357 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08004358 by Samba (not sure whether other servers allow
4359 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00004360#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04004361 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05004362 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05004363 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00004364 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05004365 SECMODE_PW_ENCRYPT ? true : false,
4366 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00004367 else
4368#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06004369 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05004370 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05004371 if (rc) {
4372 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
4373 __func__, rc);
4374 cifs_buf_release(smb_buffer);
4375 return rc;
4376 }
Steve Frencheeac8042006-01-13 21:34:58 -08004377
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004378 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004379 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00004380 /* must align unicode strings */
4381 *bcc_ptr = 0; /* null byte password */
4382 bcc_ptr++;
4383 }
Steve Frencheeac8042006-01-13 21:34:58 -08004384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385
Jeff Layton38d77c52013-05-26 07:01:00 -04004386 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4388
4389 if (ses->capabilities & CAP_STATUS32) {
4390 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
4391 }
4392 if (ses->capabilities & CAP_DFS) {
4393 smb_buffer->Flags2 |= SMBFLG2_DFS;
4394 }
4395 if (ses->capabilities & CAP_UNICODE) {
4396 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
4397 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06004398 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004399 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004400 (/* server len*/ + 256 /* share len */), nls_codepage);
4401 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402 bcc_ptr += 2; /* skip trailing null */
4403 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404 strcpy(bcc_ptr, tree);
4405 bcc_ptr += strlen(tree) + 1;
4406 }
4407 strcpy(bcc_ptr, "?????");
4408 bcc_ptr += strlen("?????");
4409 bcc_ptr += 1;
4410 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004411 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4412 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413 pSMB->ByteCount = cpu_to_le16(count);
4414
Steve French133672e2007-11-13 22:41:37 +00004415 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004416 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01004419 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004420 bool is_unicode;
4421
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004423 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424 tcon->tid = smb_buffer_response->Tid;
4425 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004426 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004427 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004428 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4429 is_unicode = true;
4430 else
4431 is_unicode = false;
4432
Jeff Laytoncc20c032009-04-30 07:16:21 -04004433
Steve French50c2f752007-07-13 00:33:32 +00004434 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004435 if (length == 3) {
4436 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4437 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004438 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01004439 tcon->ipc = true;
4440 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00004441 }
4442 } else if (length == 2) {
4443 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4444 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05004445 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004446 }
4447 }
Steve French50c2f752007-07-13 00:33:32 +00004448 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004449 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05004450 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04004451
4452 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004453 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004454 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004455 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004456 nls_codepage);
4457
Joe Perchesf96637b2013-05-04 22:12:25 -05004458 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004459
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004460 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004461 (smb_buffer_response->WordCount == 7))
4462 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004463 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4464 else
4465 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05004466 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 }
4468
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004469 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470 return rc;
4471}
4472
Al Viro2e32cf52013-10-03 12:53:37 -04004473static void delayed_free(struct rcu_head *p)
4474{
4475 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
4476 unload_nls(sbi->local_nls);
4477 kfree(sbi);
4478}
4479
Al Viro2a9b9952011-06-17 09:27:16 -04004480void
4481cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482{
Jeff Laytonb647c352010-10-28 11:16:44 -04004483 struct rb_root *root = &cifs_sb->tlink_tree;
4484 struct rb_node *node;
4485 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486
Jeff Layton2de970f2010-10-06 19:51:12 -04004487 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4488
Jeff Laytonb647c352010-10-28 11:16:44 -04004489 spin_lock(&cifs_sb->tlink_tree_lock);
4490 while ((node = rb_first(root))) {
4491 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4492 cifs_get_tlink(tlink);
4493 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4494 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004495
Jeff Laytonb647c352010-10-28 11:16:44 -04004496 spin_unlock(&cifs_sb->tlink_tree_lock);
4497 cifs_put_tlink(tlink);
4498 spin_lock(&cifs_sb->tlink_tree_lock);
4499 }
4500 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004501
Al Virod757d712011-06-17 09:42:43 -04004502 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02004503 kfree(cifs_sb->prepath);
Al Viro2e32cf52013-10-03 12:53:37 -04004504 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00004505}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004507int
4508cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509{
4510 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004511 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004513 if (!server->ops->need_neg || !server->ops->negotiate)
4514 return -ENOSYS;
4515
Jeff Layton198b5682010-04-24 07:57:48 -04004516 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004517 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04004518 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519
Pavel Shilovsky45275782012-05-17 17:53:29 +04004520 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004521
4522 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04004523 if (rc == 0) {
4524 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004525 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004526 server->tcpStatus = CifsGood;
4527 else
4528 rc = -EHOSTDOWN;
4529 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530 }
Steve French26b994f2008-08-06 05:11:33 +00004531
Jeff Layton198b5682010-04-24 07:57:48 -04004532 return rc;
4533}
Steve French26b994f2008-08-06 05:11:33 +00004534
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004535int
4536cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
4537 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04004538{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004539 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04004540 struct TCP_Server_Info *server = ses->server;
4541
Jeff Layton198b5682010-04-24 07:57:48 -04004542 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004543 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004544 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00004545
Joe Perchesf96637b2013-05-04 22:12:25 -05004546 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00004547 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004548
Shu Wangf5c4ba82017-09-08 18:48:33 +08004549 if (ses->auth_key.response) {
Steve French2a182872018-03-29 12:16:34 -05004550 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
Shu Wangf5c4ba82017-09-08 18:48:33 +08004551 ses->auth_key.response);
4552 kfree(ses->auth_key.response);
4553 ses->auth_key.response = NULL;
4554 ses->auth_key.len = 0;
4555 }
4556
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004557 if (server->ops->sess_setup)
4558 rc = server->ops->sess_setup(xid, ses, nls_info);
4559
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05004560 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05004561 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004562
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563 return rc;
4564}
4565
Jeff Layton8a8798a2012-01-17 16:09:15 -05004566static int
4567cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4568{
Jeff Layton3f618222013-06-12 19:52:14 -05004569 vol->sectype = ses->sectype;
4570
4571 /* krb5 is special, since we don't need username or pw */
4572 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05004573 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05004574
4575 return cifs_set_cifscreds(vol, ses);
4576}
4577
Steve French96daf2b2011-05-27 04:34:02 +00004578static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004579cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04004580{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004581 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004582 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4583 struct cifs_ses *ses;
4584 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004585 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004586
4587 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004588 if (vol_info == NULL)
4589 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004590
Jeff Layton9d002df2010-10-06 19:51:11 -04004591 vol_info->local_nls = cifs_sb->local_nls;
4592 vol_info->linux_uid = fsuid;
4593 vol_info->cred_uid = fsuid;
4594 vol_info->UNC = master_tcon->treeName;
4595 vol_info->retry = master_tcon->retry;
4596 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05004597 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04004598 vol_info->local_lease = master_tcon->local_lease;
4599 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004600 vol_info->sectype = master_tcon->ses->sectype;
4601 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004602
Jeff Layton8a8798a2012-01-17 16:09:15 -05004603 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4604 if (rc) {
4605 tcon = ERR_PTR(rc);
4606 goto out;
4607 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004608
4609 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304610 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004611 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304612 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004613
4614 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4615 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004616 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004617 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04004618 goto out;
4619 }
4620
4621 tcon = cifs_get_tcon(ses, vol_info);
4622 if (IS_ERR(tcon)) {
4623 cifs_put_smb_ses(ses);
4624 goto out;
4625 }
4626
Steve Frenchce558b02018-05-31 19:16:54 -05004627 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4628 if (tcon->posix_extensions)
4629 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05004630
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004631 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004632 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05004633
Jeff Layton9d002df2010-10-06 19:51:11 -04004634out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004635 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01004636 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004637 kfree(vol_info);
4638
4639 return tcon;
4640}
4641
Steve French96daf2b2011-05-27 04:34:02 +00004642struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004643cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4644{
4645 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4646}
4647
Jeff Laytonb647c352010-10-28 11:16:44 -04004648/* find and return a tlink with given uid */
4649static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004650tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04004651{
4652 struct rb_node *node = root->rb_node;
4653 struct tcon_link *tlink;
4654
4655 while (node) {
4656 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4657
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004658 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004659 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004660 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004661 node = node->rb_right;
4662 else
4663 return tlink;
4664 }
4665 return NULL;
4666}
4667
4668/* insert a tcon_link into the tree */
4669static void
4670tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4671{
4672 struct rb_node **new = &(root->rb_node), *parent = NULL;
4673 struct tcon_link *tlink;
4674
4675 while (*new) {
4676 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4677 parent = *new;
4678
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004679 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004680 new = &((*new)->rb_left);
4681 else
4682 new = &((*new)->rb_right);
4683 }
4684
4685 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4686 rb_insert_color(&new_tlink->tl_rbnode, root);
4687}
4688
Jeff Layton9d002df2010-10-06 19:51:11 -04004689/*
4690 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4691 * current task.
4692 *
4693 * If the superblock doesn't refer to a multiuser mount, then just return
4694 * the master tcon for the mount.
4695 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304696 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004697 * exists, then check to see if it's pending construction. If it is then wait
4698 * for construction to complete. Once it's no longer pending, check to see if
4699 * it failed and either return an error or retry construction, depending on
4700 * the timeout.
4701 *
4702 * If one doesn't exist then insert a new tcon_link struct into the tree and
4703 * try to construct a new one.
4704 */
4705struct tcon_link *
4706cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4707{
4708 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004709 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004710 struct tcon_link *tlink, *newtlink;
4711
4712 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4713 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4714
4715 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004716 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004717 if (tlink)
4718 cifs_get_tlink(tlink);
4719 spin_unlock(&cifs_sb->tlink_tree_lock);
4720
4721 if (tlink == NULL) {
4722 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4723 if (newtlink == NULL)
4724 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004725 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004726 newtlink->tl_tcon = ERR_PTR(-EACCES);
4727 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4728 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4729 cifs_get_tlink(newtlink);
4730
Jeff Layton9d002df2010-10-06 19:51:11 -04004731 spin_lock(&cifs_sb->tlink_tree_lock);
4732 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004733 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004734 if (tlink) {
4735 cifs_get_tlink(tlink);
4736 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004737 kfree(newtlink);
4738 goto wait_for_construction;
4739 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004740 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004741 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4742 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004743 } else {
4744wait_for_construction:
4745 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04004746 TASK_INTERRUPTIBLE);
4747 if (ret) {
4748 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10004749 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04004750 }
4751
4752 /* if it's good, return it */
4753 if (!IS_ERR(tlink->tl_tcon))
4754 return tlink;
4755
4756 /* return error if we tried this already recently */
4757 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4758 cifs_put_tlink(tlink);
4759 return ERR_PTR(-EACCES);
4760 }
4761
4762 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4763 goto wait_for_construction;
4764 }
4765
4766 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4767 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4768 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4769
4770 if (IS_ERR(tlink->tl_tcon)) {
4771 cifs_put_tlink(tlink);
4772 return ERR_PTR(-EACCES);
4773 }
4774
4775 return tlink;
4776}
Jeff Layton2de970f2010-10-06 19:51:12 -04004777
4778/*
4779 * periodic workqueue job that scans tcon_tree for a superblock and closes
4780 * out tcons.
4781 */
4782static void
4783cifs_prune_tlinks(struct work_struct *work)
4784{
4785 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4786 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004787 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00004788 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04004789 struct rb_node *tmp;
4790 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004791
Jeff Laytonb647c352010-10-28 11:16:44 -04004792 /*
4793 * Because we drop the spinlock in the loop in order to put the tlink
4794 * it's not guarded against removal of links from the tree. The only
4795 * places that remove entries from the tree are this function and
4796 * umounts. Because this function is non-reentrant and is canceled
4797 * before umount can proceed, this is safe.
4798 */
4799 spin_lock(&cifs_sb->tlink_tree_lock);
4800 node = rb_first(root);
4801 while (node != NULL) {
4802 tmp = node;
4803 node = rb_next(tmp);
4804 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4805
4806 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4807 atomic_read(&tlink->tl_count) != 0 ||
4808 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4809 continue;
4810
4811 cifs_get_tlink(tlink);
4812 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4813 rb_erase(tmp, root);
4814
Jeff Layton2de970f2010-10-06 19:51:12 -04004815 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004816 cifs_put_tlink(tlink);
4817 spin_lock(&cifs_sb->tlink_tree_lock);
4818 }
4819 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004820
Jeff Laytonda472fc2012-03-23 14:40:53 -04004821 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004822 TLINK_IDLE_EXPIRE);
4823}