blob: e8830f076a7f16a056f7eec3cf025e0e30bff9e8 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/connect.c
3 *
Steve French1080ef72011-02-24 18:07:19 +00004 * Copyright (C) International Business Machines Corp., 2002,2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
Steve Frenchfb8c4b12007-07-10 01:16:18 +000019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010024#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/list.h>
26#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090027#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/pagemap.h>
29#include <linux/ctype.h>
30#include <linux/utsname.h>
31#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070032#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070033#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000034#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070035#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080036#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040037#include <linux/namei.h>
Andrew Lunnc6e970a2017-03-28 23:45:06 +020038#include <linux/uuid.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080039#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040041#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040042#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050043#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000044#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040045#include <linux/parser.h>
Christoph Hellwig2f8b5442016-11-01 07:40:13 -060046#include <linux/bvec.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include "cifspdu.h"
48#include "cifsglob.h"
49#include "cifsproto.h"
50#include "cifs_unicode.h"
51#include "cifs_debug.h"
52#include "cifs_fs_sb.h"
53#include "ntlmssp.h"
54#include "nterr.h"
55#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053056#include "fscache.h"
Pavel Shilovsky53e0e112016-11-04 11:50:31 -070057#include "smb2proto.h"
Long Li2f894642017-11-22 17:38:34 -070058#include "smbdirect.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60#define CIFS_PORT 445
61#define RFC1001_PORT 139
62
Linus Torvalds1da177e2005-04-16 15:20:36 -070063extern mempool_t *cifs_req_poolp;
64
Jeff Layton2de970f2010-10-06 19:51:12 -040065/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040066#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040067#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040068
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040069enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040070 /* Mount options that take no arguments */
71 Opt_user_xattr, Opt_nouser_xattr,
72 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040073 Opt_forcegid, Opt_noforcegid,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040074 Opt_noblocksend, Opt_noautotune,
75 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
Steve French2baa2682014-09-27 02:19:01 -050076 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040077 Opt_mapchars, Opt_nomapchars, Opt_sfu,
78 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
79 Opt_noposixpaths, Opt_nounix,
80 Opt_nocase,
81 Opt_brl, Opt_nobrl,
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" },
132 { Opt_hard, "hard" },
133 { Opt_soft, "soft" },
134 { Opt_perm, "perm" },
135 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500136 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400137 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500138 { Opt_mapposix, "mapposix" }, /* SFM style */
139 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400140 { Opt_sfu, "sfu" },
141 { Opt_nosfu, "nosfu" },
142 { Opt_nodfs, "nodfs" },
143 { Opt_posixpaths, "posixpaths" },
144 { Opt_noposixpaths, "noposixpaths" },
145 { Opt_nounix, "nounix" },
146 { Opt_nounix, "nolinux" },
147 { Opt_nocase, "nocase" },
148 { Opt_nocase, "ignorecase" },
149 { Opt_brl, "brl" },
150 { Opt_nobrl, "nobrl" },
151 { Opt_nobrl, "nolock" },
152 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400153 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400154 { Opt_setuids, "setuids" },
155 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500156 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400157 { Opt_dynperm, "dynperm" },
158 { Opt_nodynperm, "nodynperm" },
159 { Opt_nohard, "nohard" },
160 { Opt_nosoft, "nosoft" },
161 { Opt_nointr, "nointr" },
162 { Opt_intr, "intr" },
163 { Opt_nostrictsync, "nostrictsync" },
164 { Opt_strictsync, "strictsync" },
165 { Opt_serverino, "serverino" },
166 { Opt_noserverino, "noserverino" },
167 { Opt_rwpidforward, "rwpidforward" },
168 { Opt_cifsacl, "cifsacl" },
169 { Opt_nocifsacl, "nocifsacl" },
170 { Opt_acl, "acl" },
171 { Opt_noacl, "noacl" },
172 { Opt_locallease, "locallease" },
173 { Opt_sign, "sign" },
174 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400175 { Opt_noac, "noac" },
176 { Opt_fsc, "fsc" },
177 { Opt_mfsymlinks, "mfsymlinks" },
178 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400179 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400180 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500181 { Opt_persistent, "persistenthandles"},
182 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600183 { Opt_resilient, "resilienthandles"},
184 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530185 { Opt_domainauto, "domainauto"},
Long Li8339dd32017-11-07 01:54:55 -0700186 { Opt_rdma, "rdma"},
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400187
188 { Opt_backupuid, "backupuid=%s" },
189 { Opt_backupgid, "backupgid=%s" },
190 { Opt_uid, "uid=%s" },
191 { Opt_cruid, "cruid=%s" },
192 { Opt_gid, "gid=%s" },
193 { Opt_file_mode, "file_mode=%s" },
194 { Opt_dirmode, "dirmode=%s" },
195 { Opt_dirmode, "dir_mode=%s" },
196 { Opt_port, "port=%s" },
197 { Opt_rsize, "rsize=%s" },
198 { Opt_wsize, "wsize=%s" },
199 { Opt_actimeo, "actimeo=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600200 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500201 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600202 { Opt_snapshot, "snapshot=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400203
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100204 { Opt_blank_user, "user=" },
205 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400206 { Opt_user, "user=%s" },
207 { Opt_user, "username=%s" },
208 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100209 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400210 { Opt_pass, "pass=%s" },
211 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100212 { Opt_blank_ip, "ip=" },
213 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400214 { Opt_ip, "ip=%s" },
215 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400216 { Opt_ignore, "unc=%s" },
217 { Opt_ignore, "target=%s" },
218 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400219 { Opt_domain, "dom=%s" },
220 { Opt_domain, "domain=%s" },
221 { Opt_domain, "workgroup=%s" },
222 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400223 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400224 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400225 { Opt_netbiosname, "netbiosname=%s" },
226 { Opt_servern, "servern=%s" },
227 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400228 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400229 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400230 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400231
232 { Opt_ignore, "cred" },
233 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400234 { Opt_ignore, "cred=%s" },
235 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400236 { Opt_ignore, "guest" },
237 { Opt_ignore, "rw" },
238 { Opt_ignore, "ro" },
239 { Opt_ignore, "suid" },
240 { Opt_ignore, "nosuid" },
241 { Opt_ignore, "exec" },
242 { Opt_ignore, "noexec" },
243 { Opt_ignore, "nodev" },
244 { Opt_ignore, "noauto" },
245 { Opt_ignore, "dev" },
246 { Opt_ignore, "mand" },
247 { Opt_ignore, "nomand" },
248 { Opt_ignore, "_netdev" },
249
250 { Opt_err, NULL }
251};
252
253enum {
254 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
255 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400256 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
257 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400258 Opt_sec_none,
259
260 Opt_sec_err
261};
262
263static const match_table_t cifs_secflavor_tokens = {
264 { Opt_sec_krb5, "krb5" },
265 { Opt_sec_krb5i, "krb5i" },
266 { Opt_sec_krb5p, "krb5p" },
267 { Opt_sec_ntlmsspi, "ntlmsspi" },
268 { Opt_sec_ntlmssp, "ntlmssp" },
269 { Opt_ntlm, "ntlm" },
270 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400271 { Opt_sec_ntlmv2, "nontlm" },
272 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400273 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400274 { Opt_sec_lanman, "lanman" },
275 { Opt_sec_none, "none" },
276
277 { Opt_sec_err, NULL }
278};
279
Jeff Layton15b6a472012-05-16 07:50:15 -0400280/* cache flavors */
281enum {
282 Opt_cache_loose,
283 Opt_cache_strict,
284 Opt_cache_none,
285 Opt_cache_err
286};
287
288static const match_table_t cifs_cacheflavor_tokens = {
289 { Opt_cache_loose, "loose" },
290 { Opt_cache_strict, "strict" },
291 { Opt_cache_none, "none" },
292 { Opt_cache_err, NULL }
293};
294
Jeff Layton23db65f2012-05-15 12:20:51 -0400295static const match_table_t cifs_smb_version_tokens = {
296 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600297 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000298 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500299 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500300 { Smb_302, SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600301#ifdef CONFIG_CIFS_SMB311
302 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500303 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600304#endif /* SMB311 */
Steve French9764c022017-09-17 10:41:35 -0500305 { Smb_3any, SMB3ANY_VERSION_STRING },
306 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600307 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400308};
309
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300310static int ip_connect(struct TCP_Server_Info *server);
311static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400312static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400313static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400314static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
315 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
Jeff Laytond5c56052008-12-01 18:42:33 -0500317/*
318 * cifs tcp session reconnection
319 *
320 * mark tcp session as reconnecting so temporarily locked
321 * mark all smb sessions as reconnecting for tcp session
322 * reconnect tcp session
323 * wake up waiters on reconnection? - (not needed currently)
324 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400325int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326cifs_reconnect(struct TCP_Server_Info *server)
327{
328 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500329 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000330 struct cifs_ses *ses;
331 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000332 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400333 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000336 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000337 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 next time through the loop */
339 spin_unlock(&GlobalMid_Lock);
340 return rc;
341 } else
342 server->tcpStatus = CifsNeedReconnect;
343 spin_unlock(&GlobalMid_Lock);
344 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400345 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
Joe Perchesf96637b2013-05-04 22:12:25 -0500347 cifs_dbg(FYI, "Reconnecting tcp session\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
349 /* before reconnecting the tcp session, mark the smb session (uid)
350 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500351 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
352 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530353 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500354 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000355 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500356 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500357 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000358 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500359 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100361 if (ses->tcon_ipc)
362 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530364 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500365
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500367 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500368 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000369 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500370 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
371 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800372 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500373 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
374 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 sock_release(server->ssocket);
376 server->ssocket = NULL;
377 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500378 server->sequence_number = 0;
379 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500380 kfree(server->session_key.response);
381 server->session_key.response = NULL;
382 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000383 server->lstrp = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500385 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400386 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500387 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500389 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
390 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400391 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
392 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400393 list_move(&mid_entry->qhead, &retry_list);
394 }
395 spin_unlock(&GlobalMid_Lock);
Rabin Vincent820962d2015-12-23 07:32:41 +0100396 mutex_unlock(&server->srv_mutex);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400397
Joe Perchesf96637b2013-05-04 22:12:25 -0500398 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400399 list_for_each_safe(tmp, tmp2, &retry_list) {
400 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500401 list_del_init(&mid_entry->qhead);
402 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400405 do {
Steve French6c3d8902006-07-31 22:46:20 +0000406 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300407
408 /* we should try only the port we connected to before */
Jeff Layton73e216a2013-09-05 08:38:10 -0400409 mutex_lock(&server->srv_mutex);
Long Li781a8052017-11-22 17:38:36 -0700410 if (cifs_rdma_enabled(server))
411 rc = smbd_reconnect(server);
412 else
413 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000414 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500415 cifs_dbg(FYI, "reconnect error %d\n", rc);
Federico Sauter4afe2602015-03-17 17:45:28 +0100416 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700417 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 } else {
419 atomic_inc(&tcpSesReconnectCount);
420 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000421 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000422 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000423 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100424 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400426 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500427
Sachin Prabhub8c60012016-10-20 19:52:24 -0400428 if (server->tcpStatus == CifsNeedNegotiate)
429 mod_delayed_work(cifsiod_wq, &server->echo, 0);
430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 return rc;
432}
433
Jeff Laytonc74093b2011-01-11 07:24:23 -0500434static void
435cifs_echo_request(struct work_struct *work)
436{
437 int rc;
438 struct TCP_Server_Info *server = container_of(work,
439 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400440 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500441
Jeff Layton247ec9b2011-02-04 17:09:50 -0500442 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400443 * If we need to renegotiate, set echo interval to zero to
444 * immediately call echo service where we can renegotiate.
445 */
446 if (server->tcpStatus == CifsNeedNegotiate)
447 echo_interval = 0;
448 else
449 echo_interval = server->echo_interval;
450
451 /*
452 * We cannot send an echo if it is disabled.
453 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500454 */
Steve French4fcd1812016-06-22 20:12:05 -0500455
456 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400457 server->tcpStatus == CifsExiting ||
458 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400459 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600460 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500461 goto requeue_echo;
462
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400463 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500464 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500465 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
466 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500467
468requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400469 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500470}
471
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400472static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400473allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400474{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400475 if (!server->bigbuf) {
476 server->bigbuf = (char *)cifs_buf_get();
477 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500478 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400479 msleep(3000);
480 /* retry will check if exiting */
481 return false;
482 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400483 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400484 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400485 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400486 }
487
Jeff Layton2a37ef92011-10-19 15:29:23 -0400488 if (!server->smallbuf) {
489 server->smallbuf = (char *)cifs_small_buf_get();
490 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500491 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400492 msleep(1000);
493 /* retry will check if exiting */
494 return false;
495 }
496 /* beginning of smb buffer is cleared in our buf_get */
497 } else {
498 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400499 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400500 }
501
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400502 return true;
503}
504
Jeff Laytonba749e62011-10-11 06:41:32 -0400505static bool
506server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400507{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300508 /*
509 * We need to wait 2 echo intervals to make sure we handle such
510 * situations right:
511 * 1s client sends a normal SMB request
512 * 2s client gets a response
513 * 30s echo workqueue job pops, and decides we got a response recently
514 * and don't need to send another
515 * ...
516 * 65s kernel_recvmsg times out, and we see that we haven't gotten
517 * a response in >60s.
518 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200519 if ((server->tcpStatus == CifsGood ||
520 server->tcpStatus == CifsNeedNegotiate) &&
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600521 time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
522 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
523 server->hostname, (2 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400524 cifs_reconnect(server);
525 wake_up(&server->response_q);
526 return true;
527 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400528
Jeff Laytonba749e62011-10-11 06:41:32 -0400529 return false;
530}
531
Al Viro71335662016-01-09 19:54:50 -0500532static int
533cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400534{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400535 int length = 0;
536 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400537
Al Viro71335662016-01-09 19:54:50 -0500538 smb_msg->msg_control = NULL;
539 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400540
Al Viro71335662016-01-09 19:54:50 -0500541 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500542 try_to_freeze();
543
Al Viro71335662016-01-09 19:54:50 -0500544 if (server_unresponsive(server))
545 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700546 if (cifs_rdma_enabled(server) && server->smbd_conn)
547 length = smbd_recv(server->smbd_conn, smb_msg);
548 else
549 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500550
551 if (server->tcpStatus == CifsExiting)
552 return -ESHUTDOWN;
553
554 if (server->tcpStatus == CifsNeedReconnect) {
555 cifs_reconnect(server);
556 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400557 }
558
Al Viro71335662016-01-09 19:54:50 -0500559 if (length == -ERESTARTSYS ||
560 length == -EAGAIN ||
561 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400562 /*
563 * Minimum sleep to prevent looping, allowing socket
564 * to clear and app threads to set tcpStatus
565 * CifsNeedReconnect if server hung.
566 */
567 usleep_range(1000, 2000);
568 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400569 continue;
Al Viro71335662016-01-09 19:54:50 -0500570 }
571
572 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500573 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400574 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500575 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400576 }
577 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400578 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400579}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400580
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400581int
582cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
583 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400584{
Al Viro71335662016-01-09 19:54:50 -0500585 struct msghdr smb_msg;
586 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
587 iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400588
Al Viro71335662016-01-09 19:54:50 -0500589 return cifs_readv_from_socket(server, &smb_msg);
590}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400591
Al Viro71335662016-01-09 19:54:50 -0500592int
593cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
594 unsigned int to_read)
595{
596 struct msghdr smb_msg;
597 struct bio_vec bv = {.bv_page = page, .bv_len = to_read};
598 iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
599 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400600}
601
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400602static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400603is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400604{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400605 /*
606 * The first byte big endian of the length field,
607 * is actually not part of the length but the type
608 * with the most common, zero, as regular data.
609 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400610 switch (type) {
611 case RFC1002_SESSION_MESSAGE:
612 /* Regular SMB response */
613 return true;
614 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500615 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400616 break;
617 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500618 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400619 break;
620 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400621 /*
622 * We get this from Windows 98 instead of an error on
623 * SMB negprot response.
624 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500625 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400626 /* give server a second to clean up */
627 msleep(1000);
628 /*
629 * Always try 445 first on reconnect since we get NACK
630 * on some if we ever connected to port 139 (the NACK
631 * is since we do not begin with RFC1001 session
632 * initialize frame).
633 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400634 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400635 cifs_reconnect(server);
636 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400637 break;
638 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500639 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400640 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400641 }
642
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400643 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400644}
645
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400646void
647dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400648{
649#ifdef CONFIG_CIFS_STATS2
650 mid->when_received = jiffies;
651#endif
652 spin_lock(&GlobalMid_Lock);
653 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400654 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400655 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400656 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400657 list_del_init(&mid->qhead);
658 spin_unlock(&GlobalMid_Lock);
659}
660
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400661static void
662handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400663 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400664{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400665 if (server->ops->check_trans2 &&
666 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400667 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400668 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400669 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400670 /* Was previous buf put in mpx struct for multi-rsp? */
671 if (!mid->multiRsp) {
672 /* smb buffer will be freed by user thread */
673 if (server->large_buf)
674 server->bigbuf = NULL;
675 else
676 server->smallbuf = NULL;
677 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400678 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400679}
680
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400681static void clean_demultiplex_info(struct TCP_Server_Info *server)
682{
683 int length;
684
685 /* take it off the list, if it's not already */
686 spin_lock(&cifs_tcp_ses_lock);
687 list_del_init(&server->tcp_ses_list);
688 spin_unlock(&cifs_tcp_ses_lock);
689
690 spin_lock(&GlobalMid_Lock);
691 server->tcpStatus = CifsExiting;
692 spin_unlock(&GlobalMid_Lock);
693 wake_up_all(&server->response_q);
694
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400695 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300696 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400697 if (server->credits <= 0)
698 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300699 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400700 /*
701 * Although there should not be any requests blocked on this queue it
702 * can not hurt to be paranoid and try to wake up requests that may
703 * haven been blocked when more than 50 at time were on the wire to the
704 * same server - they now will see the session is in exit state and get
705 * out of SendReceive.
706 */
707 wake_up_all(&server->request_q);
708 /* give those requests time to exit */
709 msleep(125);
Long Libce9ce72017-11-22 17:38:38 -0700710 if (cifs_rdma_enabled(server) && server->smbd_conn) {
711 smbd_destroy(server->smbd_conn);
712 server->smbd_conn = NULL;
713 }
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400714 if (server->ssocket) {
715 sock_release(server->ssocket);
716 server->ssocket = NULL;
717 }
718
719 if (!list_empty(&server->pending_mid_q)) {
720 struct list_head dispose_list;
721 struct mid_q_entry *mid_entry;
722 struct list_head *tmp, *tmp2;
723
724 INIT_LIST_HEAD(&dispose_list);
725 spin_lock(&GlobalMid_Lock);
726 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
727 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500728 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400729 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400730 list_move(&mid_entry->qhead, &dispose_list);
731 }
732 spin_unlock(&GlobalMid_Lock);
733
734 /* now walk dispose list and issue callbacks */
735 list_for_each_safe(tmp, tmp2, &dispose_list) {
736 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500737 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400738 list_del_init(&mid_entry->qhead);
739 mid_entry->callback(mid_entry);
740 }
741 /* 1/8th of sec is more than enough time for them to exit */
742 msleep(125);
743 }
744
745 if (!list_empty(&server->pending_mid_q)) {
746 /*
747 * mpx threads have not exited yet give them at least the smb
748 * send timeout time for long ops.
749 *
750 * Due to delays on oplock break requests, we need to wait at
751 * least 45 seconds before giving up on a request getting a
752 * response and going ahead and killing cifsd.
753 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500754 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400755 msleep(46000);
756 /*
757 * If threads still have not exited they are probably never
758 * coming home not much else we can do but free the memory.
759 */
760 }
761
762 kfree(server->hostname);
763 kfree(server);
764
765 length = atomic_dec_return(&tcpSesAllocCount);
766 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700767 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400768}
769
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400770static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400771standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
772{
773 int length;
774 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +1000775 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400776
777 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100778 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
779 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500780 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400781 cifs_reconnect(server);
782 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400783 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400784 }
785
786 /* switch to large buffer if too big for a small one */
787 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
788 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400789 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400790 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400791 }
792
793 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400794 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100795 pdu_length - HEADER_SIZE(server) + 1
796 + server->vals->header_preamble_size);
797
Jeff Laytone9097ab2011-10-19 15:29:40 -0400798 if (length < 0)
799 return length;
800 server->total_read += length;
801
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400802 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400803
Pavel Shilovsky4326ed22016-11-17 15:24:46 -0800804 return cifs_handle_standard(server, mid);
805}
806
807int
808cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
809{
810 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
811 int length;
812
Jeff Laytone9097ab2011-10-19 15:29:40 -0400813 /*
814 * We know that we received enough to get to the MID as we
815 * checked the pdu_length earlier. Now check to see
816 * if the rest of the header is OK. We borrow the length
817 * var for the rest of the loop to avoid a new stack var.
818 *
819 * 48 bytes is enough to display the header and a little bit
820 * into the payload for debugging purposes.
821 */
Steve French373512e2015-12-18 13:05:30 -0600822 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400823 if (length != 0)
824 cifs_dump_mem("Bad SMB: ", buf,
825 min_t(unsigned int, server->total_read, 48));
826
Pavel Shilovsky511c54a2017-07-08 14:32:00 -0700827 if (server->ops->is_session_expired &&
828 server->ops->is_session_expired(buf)) {
829 cifs_reconnect(server);
830 wake_up(&server->response_q);
831 return -1;
832 }
833
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700834 if (server->ops->is_status_pending &&
835 server->ops->is_status_pending(buf, server, length))
836 return -1;
837
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500838 if (!mid)
839 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400840
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400841 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500842 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400843}
844
845static int
Al Viro7c97c202011-06-21 08:51:28 -0400846cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847{
848 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400849 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400850 unsigned int pdu_length;
851 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500852 struct task_struct *task_to_wake = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -0500856 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400857
858 length = atomic_inc_return(&tcpSesAllocCount);
859 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -0700860 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700862 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +0000863 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700864 if (try_to_freeze())
865 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700866
Jeff Layton2a37ef92011-10-19 15:29:23 -0400867 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400868 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700869
Jeff Layton2a37ef92011-10-19 15:29:23 -0400870 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400871 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000872 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000873
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400874 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400875 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +0000876 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400877 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700878
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400879 /*
880 * The right amount was read from socket - 4 bytes,
881 * so we can now interpret the length field.
882 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400883 pdu_length = get_rfc1002_length(buf);
Ronnie Sahlberg2e964672018-04-09 18:06:26 +1000884 server->pdu_size = pdu_length;
Steve French46810cb2005-04-28 22:41:09 -0700885
Joe Perchesf96637b2013-05-04 22:12:25 -0500886 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400887 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000888 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700889
Jeff Layton89482a52011-10-19 15:28:57 -0400890 /* make sure we have enough to get to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100891 if (pdu_length < HEADER_SIZE(server) - 1 -
892 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500893 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
894 pdu_length);
Jeff Layton89482a52011-10-19 15:28:57 -0400895 cifs_reconnect(server);
896 wake_up(&server->response_q);
897 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700898 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400899
Jeff Layton89482a52011-10-19 15:28:57 -0400900 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100901 length = cifs_read_from_socket(server,
902 buf + server->vals->header_preamble_size,
903 HEADER_SIZE(server) - 1
904 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -0400905 if (length < 0)
906 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400907 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -0400908
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -0800909 if (server->ops->is_transform_hdr &&
910 server->ops->receive_transform &&
911 server->ops->is_transform_hdr(buf)) {
912 length = server->ops->receive_transform(server,
913 &mid_entry);
914 } else {
915 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400916
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -0800917 if (!mid_entry || !mid_entry->receive)
918 length = standard_receive3(server, mid_entry);
919 else
920 length = mid_entry->receive(server, mid_entry);
921 }
Jeff Layton44d22d82011-10-19 15:29:49 -0400922
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400923 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -0700924 continue;
925
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400926 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -0400927 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -0700928
Steve Frenchfda35942011-01-20 18:06:34 +0000929 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500930 if (mid_entry != NULL) {
Ronnie Sahlberge19b2bc2018-04-09 18:06:28 +1000931 mid_entry->resp_buf_size = server->pdu_size;
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800932 if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
933 mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
934 server->ops->handle_cancelled_mid)
935 server->ops->handle_cancelled_mid(
936 mid_entry->resp_buf,
937 server);
938
Jeff Layton2a37ef92011-10-19 15:29:23 -0400939 if (!mid_entry->multiRsp || mid_entry->multiEnd)
940 mid_entry->callback(mid_entry);
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800941 } else if (server->ops->is_oplock_break &&
942 server->ops->is_oplock_break(buf, server)) {
943 cifs_dbg(FYI, "Received oplock break\n");
944 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -0500945 cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
946 atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400947 cifs_dump_mem("Received Data is: ", buf,
948 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +0000949#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400950 if (server->ops->dump_detail)
951 server->ops->dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +0000952 cifs_dump_mids(server);
953#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +0000954
Steve Frenche4eb2952005-04-28 22:41:09 -0700955 }
956 } /* end while !EXITING */
957
Justin P. Mattockfd62cb72011-02-24 22:15:02 -0800958 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -0400959 cifs_buf_release(server->bigbuf);
960 if (server->smallbuf) /* no sense logging a debug message if NULL */
961 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500963 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400964 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500965
966 /* if server->tsk was NULL then wait for a signal before exiting */
967 if (!task_to_wake) {
968 set_current_state(TASK_INTERRUPTIBLE);
969 while (!signal_pending(current)) {
970 schedule();
971 set_current_state(TASK_INTERRUPTIBLE);
972 }
973 set_current_state(TASK_RUNNING);
974 }
975
Jeff Layton0468a2c2008-12-01 07:09:35 -0500976 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977}
978
Jeff Laytonc359cf32007-11-16 22:22:06 +0000979/* extract the host portion of the UNC string */
980static char *
981extract_hostname(const char *unc)
982{
983 const char *src;
984 char *dst, *delim;
985 unsigned int len;
986
987 /* skip double chars at beginning of string */
988 /* BB: check validity of these bytes? */
989 src = unc + 2;
990
991 /* delimiter between hostname and sharename is always '\\' now */
992 delim = strchr(src, '\\');
993 if (!delim)
994 return ERR_PTR(-EINVAL);
995
996 len = delim - src;
997 dst = kmalloc((len + 1), GFP_KERNEL);
998 if (dst == NULL)
999 return ERR_PTR(-ENOMEM);
1000
1001 memcpy(dst, src, len);
1002 dst[len] = '\0';
1003
1004 return dst;
1005}
1006
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001007static int get_option_ul(substring_t args[], unsigned long *option)
1008{
1009 int rc;
1010 char *string;
1011
1012 string = match_strdup(args);
1013 if (string == NULL)
1014 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001015 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001016 kfree(string);
1017
1018 return rc;
1019}
1020
Eric W. Biederman3da46562013-02-06 01:37:39 -08001021static int get_option_uid(substring_t args[], kuid_t *result)
1022{
1023 unsigned long value;
1024 kuid_t uid;
1025 int rc;
1026
1027 rc = get_option_ul(args, &value);
1028 if (rc)
1029 return rc;
1030
1031 uid = make_kuid(current_user_ns(), value);
1032 if (!uid_valid(uid))
1033 return -EINVAL;
1034
1035 *result = uid;
1036 return 0;
1037}
1038
1039static int get_option_gid(substring_t args[], kgid_t *result)
1040{
1041 unsigned long value;
1042 kgid_t gid;
1043 int rc;
1044
1045 rc = get_option_ul(args, &value);
1046 if (rc)
1047 return rc;
1048
1049 gid = make_kgid(current_user_ns(), value);
1050 if (!gid_valid(gid))
1051 return -EINVAL;
1052
1053 *result = gid;
1054 return 0;
1055}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001056
1057static int cifs_parse_security_flavors(char *value,
1058 struct smb_vol *vol)
1059{
1060
1061 substring_t args[MAX_OPT_ARGS];
1062
Jeff Layton1e3cc572013-06-10 17:12:23 -05001063 /*
1064 * With mount options, the last one should win. Reset any existing
1065 * settings back to default.
1066 */
1067 vol->sectype = Unspecified;
1068 vol->sign = false;
1069
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001070 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001071 case Opt_sec_krb5p:
1072 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1073 return 1;
1074 case Opt_sec_krb5i:
1075 vol->sign = true;
1076 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001077 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001078 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001079 break;
1080 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001081 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001082 /* Fallthrough */
1083 case Opt_sec_ntlmssp:
1084 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001085 break;
1086 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001087 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001088 /* Fallthrough */
1089 case Opt_ntlm:
1090 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001091 break;
1092 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001093 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001094 /* Fallthrough */
1095 case Opt_sec_ntlmv2:
1096 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001097 break;
1098#ifdef CONFIG_CIFS_WEAK_PW_HASH
1099 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001100 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001101 break;
1102#endif
1103 case Opt_sec_none:
1104 vol->nullauth = 1;
1105 break;
1106 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001107 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001108 return 1;
1109 }
1110
1111 return 0;
1112}
1113
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001115cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1116{
1117 substring_t args[MAX_OPT_ARGS];
1118
1119 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1120 case Opt_cache_loose:
1121 vol->direct_io = false;
1122 vol->strict_io = false;
1123 break;
1124 case Opt_cache_strict:
1125 vol->direct_io = false;
1126 vol->strict_io = true;
1127 break;
1128 case Opt_cache_none:
1129 vol->direct_io = true;
1130 vol->strict_io = false;
1131 break;
1132 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001133 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001134 return 1;
1135 }
1136 return 0;
1137}
1138
1139static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001140cifs_parse_smb_version(char *value, struct smb_vol *vol)
1141{
1142 substring_t args[MAX_OPT_ARGS];
1143
1144 switch (match_token(value, cifs_smb_version_tokens, args)) {
1145 case Smb_1:
1146 vol->ops = &smb1_operations;
1147 vol->vals = &smb1_values;
1148 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001149 case Smb_20:
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001150 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001151 vol->vals = &smb20_values;
1152 break;
Steve French1080ef72011-02-24 18:07:19 +00001153 case Smb_21:
1154 vol->ops = &smb21_operations;
1155 vol->vals = &smb21_values;
1156 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001157 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001158 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001159 vol->vals = &smb30_values;
1160 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001161 case Smb_302:
1162 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1163 vol->vals = &smb302_values;
1164 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001165#ifdef CONFIG_CIFS_SMB311
1166 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001167 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001168 vol->vals = &smb311_values;
1169 break;
1170#endif /* SMB311 */
Steve French9764c022017-09-17 10:41:35 -05001171 case Smb_3any:
1172 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1173 vol->vals = &smb3any_values;
1174 break;
1175 case Smb_default:
1176 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1177 vol->vals = &smbdefault_values;
1178 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001179 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001180 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001181 return 1;
1182 }
1183 return 0;
1184}
1185
Jeff Laytond387a5c2012-12-10 06:10:46 -05001186/*
1187 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1188 * fields with the result. Returns 0 on success and an error otherwise.
1189 */
1190static int
1191cifs_parse_devname(const char *devname, struct smb_vol *vol)
1192{
1193 char *pos;
1194 const char *delims = "/\\";
1195 size_t len;
1196
1197 /* make sure we have a valid UNC double delimiter prefix */
1198 len = strspn(devname, delims);
1199 if (len != 2)
1200 return -EINVAL;
1201
1202 /* find delimiter between host and sharename */
1203 pos = strpbrk(devname + 2, delims);
1204 if (!pos)
1205 return -EINVAL;
1206
1207 /* skip past delimiter */
1208 ++pos;
1209
1210 /* now go until next delimiter or end of string */
1211 len = strcspn(pos, delims);
1212
1213 /* move "pos" up to delimiter or NULL */
1214 pos += len;
1215 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1216 if (!vol->UNC)
1217 return -ENOMEM;
1218
1219 convert_delimiter(vol->UNC, '\\');
1220
Sachin Prabhu11e31642016-02-08 13:44:01 +05301221 /* skip any delimiter */
1222 if (*pos == '/' || *pos == '\\')
1223 pos++;
1224
1225 /* If pos is NULL then no prepath */
1226 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001227 return 0;
1228
1229 vol->prepath = kstrdup(pos, GFP_KERNEL);
1230 if (!vol->prepath)
1231 return -ENOMEM;
1232
1233 return 0;
1234}
1235
Jeff Layton23db65f2012-05-15 12:20:51 -04001236static int
Sean Finneyb9468452011-04-11 13:19:32 +00001237cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001238 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001240 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001241 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 unsigned int temp_len, i, j;
1243 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001244 short int override_uid = -1;
1245 short int override_gid = -1;
1246 bool uid_specified = false;
1247 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001248 bool sloppy = false;
1249 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001250 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001251 char *string = NULL;
1252 char *tmp_end, *value;
1253 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001254 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001255 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001256 unsigned short port = 0;
1257 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
1259 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001260 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001261 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
Jeff Layton6ee95422012-11-26 11:09:57 -05001263 /* ensure we always start with zeroed-out smb_vol */
1264 memset(vol, 0, sizeof(*vol));
1265
Jeff Layton88463992010-11-22 15:31:03 -05001266 /*
1267 * does not have to be perfect mapping since field is
1268 * informational, only used for servers that do not support
1269 * port 445 and it can be overridden at mount time
1270 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001271 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1272 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001273 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1274
Jeff Layton1397f2e2011-01-07 11:30:28 -05001275 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001276 /* null target name indicates to use *SMBSERVR default called name
1277 if we end up sending RFC1001 session initialize */
1278 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001279 vol->cred_uid = current_uid();
1280 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001281 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001282
Steve French2baa2682014-09-27 02:19:01 -05001283 /*
1284 * default to SFM style remapping of seven reserved characters
1285 * unless user overrides it or we negotiate CIFS POSIX where
1286 * it is unnecessary. Can not simultaneously use more than one mapping
1287 * since then readdir could list files that open could not open
1288 */
1289 vol->remap = true;
1290
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001291 /* default to only allowing write access to owner of the mount */
1292 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
1294 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001295 /* default is always to request posix paths. */
1296 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001297 /* default to using server inode numbers where available */
1298 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001299
Jeff Layton1b359202012-09-19 15:20:27 -07001300 /* default is to use strict cifs caching semantics */
1301 vol->strict_io = true;
1302
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301303 vol->actimeo = CIFS_DEF_ACTIMEO;
1304
Steve French9764c022017-09-17 10:41:35 -05001305 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1306 vol->ops = &smb30_operations;
1307 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001308
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001309 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1310
Sean Finneyb9468452011-04-11 13:19:32 +00001311 if (!mountdata)
1312 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
Sean Finneyb9468452011-04-11 13:19:32 +00001314 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1315 if (!mountdata_copy)
1316 goto cifs_parse_mount_err;
1317
1318 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001319 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001320
Steve French50c2f752007-07-13 00:33:32 +00001321 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001322 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 separator[0] = options[4];
1324 options += 5;
1325 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001326 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 }
1328 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001329 vol->backupuid_specified = false; /* no backup intent for a user */
1330 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001331
Jeff Layton37d4f992013-05-24 07:40:05 -04001332 switch (cifs_parse_devname(devname, vol)) {
1333 case 0:
1334 break;
1335 case -ENOMEM:
1336 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1337 goto cifs_parse_mount_err;
1338 case -EINVAL:
1339 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1340 goto cifs_parse_mount_err;
1341 default:
1342 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1343 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001344 }
1345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001347 substring_t args[MAX_OPT_ARGS];
1348 unsigned long option;
1349 int token;
1350
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 if (!*data)
1352 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001354 token = match_token(data, cifs_mount_option_tokens, args);
1355
1356 switch (token) {
1357
1358 /* Ingnore the following */
1359 case Opt_ignore:
1360 break;
1361
1362 /* Boolean values */
1363 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001365 break;
1366 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001368 break;
1369 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001370 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001371 break;
1372 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001373 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001374 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001375 case Opt_forcegid:
1376 override_gid = 1;
1377 break;
1378 case Opt_noforcegid:
1379 override_gid = 0;
1380 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001381 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001382 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 break;
1384 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001385 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001386 break;
1387 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001389 break;
1390 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001392 break;
1393 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001395 break;
1396 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001398 break;
1399 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001400 vol->sfu_remap = true;
1401 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001402 break;
1403 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001404 vol->sfu_remap = false;
1405 break;
1406 case Opt_mapposix:
1407 vol->remap = true;
1408 vol->sfu_remap = false; /* disable SFU mapping */
1409 break;
1410 case Opt_nomapposix:
1411 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001412 break;
1413 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001414 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001415 break;
1416 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001417 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001418 break;
1419 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001420 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001421 break;
1422 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001423 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001424 break;
1425 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001426 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001427 break;
1428 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001429 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001430 break;
1431 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001432 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001433 break;
1434 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001435 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001436 break;
1437 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001438 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001439 /*
1440 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001441 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001442 * local vfs will do advisory
1443 */
Steve French50c2f752007-07-13 00:33:32 +00001444 if (vol->file_mode ==
1445 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001446 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001447 break;
1448 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001449 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001450 break;
1451 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001453 break;
1454 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001456 break;
Steve French95932652016-09-23 01:36:34 -05001457 case Opt_setuidfromacl:
1458 vol->setuidfromacl = 1;
1459 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001461 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001462 break;
1463 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001464 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001465 break;
1466 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001468 break;
1469 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001471 break;
1472 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001474 break;
1475 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001477 break;
1478 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001479 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001480 break;
1481 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001482 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001483 break;
1484 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001486 break;
1487 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001489 break;
1490 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001491 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001492 break;
1493 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001494 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001495 break;
1496 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001497 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001498 break;
1499 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001501 break;
1502 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001504 break;
1505 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001506 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001507 break;
1508 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001509 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001510 break;
1511 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001512 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001513 * is a per tree connection (mount) not a per socket
1514 * or per-smb connection option in the protocol
1515 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1516 */
Steve French95b1cb92008-05-15 16:44:38 +00001517 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001518 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001519 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001520 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001521 break;
1522 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301523#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001524 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001525 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301526#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301527 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001528 break;
1529 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001530 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001531 break;
1532 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001533 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001534 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001535 case Opt_sloppy:
1536 sloppy = true;
1537 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001538 case Opt_nosharesock:
1539 vol->nosharesock = true;
1540 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001541 case Opt_nopersistent:
1542 vol->nopersistent = true;
1543 if (vol->persistent) {
1544 cifs_dbg(VFS,
1545 "persistenthandles mount options conflict\n");
1546 goto cifs_parse_mount_err;
1547 }
1548 break;
1549 case Opt_persistent:
1550 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001551 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001552 cifs_dbg(VFS,
1553 "persistenthandles mount options conflict\n");
1554 goto cifs_parse_mount_err;
1555 }
1556 break;
Steve French592fafe2015-11-03 10:08:53 -06001557 case Opt_resilient:
1558 vol->resilient = true;
1559 if (vol->persistent) {
1560 cifs_dbg(VFS,
1561 "persistenthandles mount options conflict\n");
1562 goto cifs_parse_mount_err;
1563 }
1564 break;
1565 case Opt_noresilient:
1566 vol->resilient = false; /* already the default */
1567 break;
Germano Percossi39566442016-12-15 12:31:18 +05301568 case Opt_domainauto:
1569 vol->domainauto = true;
1570 break;
Long Li8339dd32017-11-07 01:54:55 -07001571 case Opt_rdma:
1572 vol->rdma = true;
1573 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001574
1575 /* Numeric Values */
1576 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001577 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001578 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1579 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001580 goto cifs_parse_mount_err;
1581 }
1582 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001583 break;
1584 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001585 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001586 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1587 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001588 goto cifs_parse_mount_err;
1589 }
1590 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001591 break;
1592 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001593 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001594 cifs_dbg(VFS, "%s: Invalid uid value\n",
1595 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001596 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001598 uid_specified = true;
1599 break;
1600 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001601 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001602 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1603 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001604 goto cifs_parse_mount_err;
1605 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001606 break;
1607 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001608 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001609 cifs_dbg(VFS, "%s: Invalid gid value\n",
1610 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001611 goto cifs_parse_mount_err;
1612 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001613 gid_specified = true;
1614 break;
1615 case Opt_file_mode:
1616 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001617 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1618 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001619 goto cifs_parse_mount_err;
1620 }
1621 vol->file_mode = option;
1622 break;
1623 case Opt_dirmode:
1624 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001625 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1626 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001627 goto cifs_parse_mount_err;
1628 }
1629 vol->dir_mode = option;
1630 break;
1631 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001632 if (get_option_ul(args, &option) ||
1633 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001634 cifs_dbg(VFS, "%s: Invalid port value\n",
1635 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001636 goto cifs_parse_mount_err;
1637 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001638 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001639 break;
1640 case Opt_rsize:
1641 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001642 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1643 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001644 goto cifs_parse_mount_err;
1645 }
1646 vol->rsize = option;
1647 break;
1648 case Opt_wsize:
1649 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001650 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1651 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001652 goto cifs_parse_mount_err;
1653 }
1654 vol->wsize = option;
1655 break;
1656 case Opt_actimeo:
1657 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001658 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1659 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001660 goto cifs_parse_mount_err;
1661 }
1662 vol->actimeo = HZ * option;
1663 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001664 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001665 goto cifs_parse_mount_err;
1666 }
1667 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06001668 case Opt_echo_interval:
1669 if (get_option_ul(args, &option)) {
1670 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
1671 __func__);
1672 goto cifs_parse_mount_err;
1673 }
1674 vol->echo_interval = option;
1675 break;
Steve French8b217fe2016-11-11 22:36:20 -06001676 case Opt_snapshot:
1677 if (get_option_ul(args, &option)) {
1678 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
1679 __func__);
1680 goto cifs_parse_mount_err;
1681 }
1682 vol->snapshot_time = option;
1683 break;
Steve French141891f2016-09-23 00:44:16 -05001684 case Opt_max_credits:
1685 if (get_option_ul(args, &option) || (option < 20) ||
1686 (option > 60000)) {
1687 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1688 __func__);
1689 goto cifs_parse_mount_err;
1690 }
1691 vol->max_credits = option;
1692 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001693
1694 /* String Arguments */
1695
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001696 case Opt_blank_user:
1697 /* null user, ie. anonymous authentication */
1698 vol->nullauth = 1;
1699 vol->username = NULL;
1700 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001701 case Opt_user:
1702 string = match_strdup(args);
1703 if (string == NULL)
1704 goto out_nomem;
1705
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001706 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1707 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001708 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001709 goto cifs_parse_mount_err;
1710 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001711
1712 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001713 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001714 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001715 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001716 break;
1717 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001718 /* passwords have to be handled differently
1719 * to allow the character used for deliminator
1720 * to be passed within them
1721 */
1722
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001723 /*
1724 * Check if this is a case where the password
1725 * starts with a delimiter
1726 */
1727 tmp_end = strchr(data, '=');
1728 tmp_end++;
1729 if (!(tmp_end < end && tmp_end[1] == delim)) {
1730 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01001731 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001732 vol->password = NULL;
1733 break;
1734 }
1735 /* Yes it is. Drop down to Opt_pass below.*/
1736 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001737 /* Obtain the value string */
1738 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001739 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001740
1741 /* Set tmp_end to end of the string */
1742 tmp_end = (char *) value + strlen(value);
1743
1744 /* Check if following character is the deliminator
1745 * If yes, we have encountered a double deliminator
1746 * reset the NULL character to the deliminator
1747 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301748 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001749 tmp_end[0] = delim;
1750
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301751 /* Keep iterating until we get to a single
1752 * deliminator OR the end
1753 */
1754 while ((tmp_end = strchr(tmp_end, delim))
1755 != NULL && (tmp_end[1] == delim)) {
1756 tmp_end = (char *) &tmp_end[2];
1757 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001758
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301759 /* Reset var options to point to next element */
1760 if (tmp_end) {
1761 tmp_end[0] = '\0';
1762 options = (char *) &tmp_end[1];
1763 } else
1764 /* Reached the end of the mount option
1765 * string */
1766 options = end;
1767 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001768
Aurelien Aptel97f4b722018-01-25 15:59:39 +01001769 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001770 /* Now build new password string */
1771 temp_len = strlen(value);
1772 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1773 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001774 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001775 goto cifs_parse_mount_err;
1776 }
1777
1778 for (i = 0, j = 0; i < temp_len; i++, j++) {
1779 vol->password[j] = value[i];
1780 if ((value[i] == delim) &&
1781 value[i+1] == delim)
1782 /* skip the second deliminator */
1783 i++;
1784 }
1785 vol->password[j] = '\0';
1786 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001787 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001788 /* FIXME: should this be an error instead? */
1789 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001790 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001791 case Opt_ip:
1792 string = match_strdup(args);
1793 if (string == NULL)
1794 goto out_nomem;
1795
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001796 if (!cifs_convert_address(dstaddr, string,
1797 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001798 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001799 goto cifs_parse_mount_err;
1800 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001801 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001802 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 case Opt_domain:
1804 string = match_strdup(args);
1805 if (string == NULL)
1806 goto out_nomem;
1807
Chen Gang057d6332013-07-19 09:01:36 +08001808 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
1809 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001810 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001811 goto cifs_parse_mount_err;
1812 }
1813
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001814 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001815 vol->domainname = kstrdup(string, GFP_KERNEL);
1816 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001817 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001818 goto cifs_parse_mount_err;
1819 }
Joe Perchesf96637b2013-05-04 22:12:25 -05001820 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001821 break;
1822 case Opt_srcaddr:
1823 string = match_strdup(args);
1824 if (string == NULL)
1825 goto out_nomem;
1826
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001827 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001828 (struct sockaddr *)&vol->srcaddr,
1829 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001830 pr_warn("CIFS: Could not parse srcaddr: %s\n",
1831 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001832 goto cifs_parse_mount_err;
1833 }
1834 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001835 case Opt_iocharset:
1836 string = match_strdup(args);
1837 if (string == NULL)
1838 goto out_nomem;
1839
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001840 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001841 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001842 goto cifs_parse_mount_err;
1843 }
1844
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001845 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001846 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001847 vol->iocharset = kstrdup(string,
1848 GFP_KERNEL);
1849 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001850 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001851 goto cifs_parse_mount_err;
1852 }
1853 }
1854 /* if iocharset not set then load_nls_default
1855 * is used by caller
1856 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001857 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001858 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001859 case Opt_netbiosname:
1860 string = match_strdup(args);
1861 if (string == NULL)
1862 goto out_nomem;
1863
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001864 memset(vol->source_rfc1001_name, 0x20,
1865 RFC1001_NAME_LEN);
1866 /*
1867 * FIXME: are there cases in which a comma can
1868 * be valid in workstation netbios name (and
1869 * need special handling)?
1870 */
1871 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1872 /* don't ucase netbiosname for user */
1873 if (string[i] == 0)
1874 break;
1875 vol->source_rfc1001_name[i] = string[i];
1876 }
1877 /* The string has 16th byte zero still from
1878 * set at top of the function
1879 */
1880 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001881 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001882 break;
1883 case Opt_servern:
1884 /* servernetbiosname specified override *SMBSERVER */
1885 string = match_strdup(args);
1886 if (string == NULL)
1887 goto out_nomem;
1888
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001889 /* last byte, type, is 0x20 for servr type */
1890 memset(vol->target_rfc1001_name, 0x20,
1891 RFC1001_NAME_LEN_WITH_NULL);
1892
1893 /* BB are there cases in which a comma can be
1894 valid in this workstation netbios name
1895 (and need special handling)? */
1896
1897 /* user or mount helper must uppercase the
1898 netbios name */
1899 for (i = 0; i < 15; i++) {
1900 if (string[i] == 0)
1901 break;
1902 vol->target_rfc1001_name[i] = string[i];
1903 }
1904 /* The string has 16th byte zero still from
1905 set at top of the function */
1906 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001907 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001908 break;
1909 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05001910 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001911 string = match_strdup(args);
1912 if (string == NULL)
1913 goto out_nomem;
1914
Steve French7e682f72017-08-31 21:34:24 -05001915 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001916 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05001917 if (strlen(string) > 1) {
1918 pr_warn("Bad mount helper ver=%s. Did "
1919 "you want SMB1 (CIFS) dialect "
1920 "and mean to type vers=1.0 "
1921 "instead?\n", string);
1922 goto cifs_parse_mount_err;
1923 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001924 /* This is the default */
1925 break;
1926 }
1927 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05001928 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001929 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001930 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05001931 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04001932 string = match_strdup(args);
1933 if (string == NULL)
1934 goto out_nomem;
1935
1936 if (cifs_parse_smb_version(string, vol) != 0)
1937 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05001938 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04001939 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001940 case Opt_sec:
1941 string = match_strdup(args);
1942 if (string == NULL)
1943 goto out_nomem;
1944
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001945 if (cifs_parse_security_flavors(string, vol) != 0)
1946 goto cifs_parse_mount_err;
1947 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001948 case Opt_cache:
1949 string = match_strdup(args);
1950 if (string == NULL)
1951 goto out_nomem;
1952
1953 if (cifs_parse_cache_flavor(string, vol) != 0)
1954 goto cifs_parse_mount_err;
1955 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001956 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001957 /*
1958 * An option we don't recognize. Save it off for later
1959 * if we haven't already found one
1960 */
1961 if (!invalid)
1962 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001963 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001965 /* Free up any allocated string */
1966 kfree(string);
1967 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001969
Jeff Laytond8162552012-03-23 14:40:56 -04001970 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001971 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04001972 goto cifs_parse_mount_err;
1973 }
1974
Long Li8339dd32017-11-07 01:54:55 -07001975 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
1976 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
1977 goto cifs_parse_mount_err;
1978 }
1979
Long Li8801e902017-11-22 17:38:49 -07001980#ifdef CONFIG_CIFS_SMB_DIRECT
1981 if (vol->rdma && vol->sign) {
1982 cifs_dbg(VFS, "Currently SMB direct doesn't support signing."
1983 " This is being fixed\n");
1984 goto cifs_parse_mount_err;
1985 }
1986#endif
1987
Jeff Layton8a8798a2012-01-17 16:09:15 -05001988#ifndef CONFIG_KEYS
1989 /* Muliuser mounts require CONFIG_KEYS support */
1990 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001991 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001992 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001993 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001994#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001995 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04001996 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001997 goto cifs_parse_mount_err;
1998 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001999
Jeff Layton62a1a432012-12-10 06:10:45 -05002000 /* make sure UNC has a share name */
2001 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002002 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002003 goto cifs_parse_mount_err;
2004 }
2005
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002006 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002007 int len;
2008 const char *slash;
2009
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002010 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002011 /* Use the address part of the UNC. */
2012 slash = strchr(&vol->UNC[2], '\\');
2013 len = slash - &vol->UNC[2];
2014 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002015 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002016 goto cifs_parse_mount_err;
2017 }
2018 }
2019
2020 /* set the port that we got earlier */
2021 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002023 if (uid_specified)
2024 vol->override_uid = override_uid;
2025 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002026 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002027
2028 if (gid_specified)
2029 vol->override_gid = override_gid;
2030 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002031 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002032
Steve French7e682f72017-08-31 21:34:24 -05002033 if (got_version == false)
2034 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002035 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002036 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002037 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2038 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002039
Sean Finneyb9468452011-04-11 13:19:32 +00002040 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002042
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002043out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002044 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002045cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002046 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002047 kfree(mountdata_copy);
2048 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049}
2050
Ben Greear3eb9a882010-09-01 17:06:02 -07002051/** Returns true if srcaddr isn't specified and rhs isn't
2052 * specified, or if srcaddr is specified and
2053 * matches the IP address of the rhs argument.
2054 */
Jeff Layton45151482010-07-06 20:43:02 -04002055static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002056srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2057{
2058 switch (srcaddr->sa_family) {
2059 case AF_UNSPEC:
2060 return (rhs->sa_family == AF_UNSPEC);
2061 case AF_INET: {
2062 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2063 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2064 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2065 }
2066 case AF_INET6: {
2067 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002068 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002069 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2070 }
2071 default:
2072 WARN_ON(1);
2073 return false; /* don't expect to be here */
2074 }
2075}
2076
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002077/*
2078 * If no port is specified in addr structure, we try to match with 445 port
2079 * and if it fails - with 139 ports. It should be called only if address
2080 * families of server and addr are equal.
2081 */
2082static bool
2083match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2084{
Steve French6da97912011-03-13 18:55:55 +00002085 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002086
2087 switch (addr->sa_family) {
2088 case AF_INET:
2089 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2090 port = ((struct sockaddr_in *) addr)->sin_port;
2091 break;
2092 case AF_INET6:
2093 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2094 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2095 break;
2096 default:
2097 WARN_ON(1);
2098 return false;
2099 }
2100
2101 if (!port) {
2102 port = htons(CIFS_PORT);
2103 if (port == *sport)
2104 return true;
2105
2106 port = htons(RFC1001_PORT);
2107 }
2108
2109 return port == *sport;
2110}
Ben Greear3eb9a882010-09-01 17:06:02 -07002111
2112static bool
2113match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2114 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115{
Jeff Layton45151482010-07-06 20:43:02 -04002116 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002117 case AF_INET: {
2118 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2119 struct sockaddr_in *srv_addr4 =
2120 (struct sockaddr_in *)&server->dstaddr;
2121
2122 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002123 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002124 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002125 }
2126 case AF_INET6: {
2127 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2128 struct sockaddr_in6 *srv_addr6 =
2129 (struct sockaddr_in6 *)&server->dstaddr;
2130
Jeff Layton45151482010-07-06 20:43:02 -04002131 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002132 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002133 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002134 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002135 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002136 break;
2137 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002138 default:
2139 WARN_ON(1);
2140 return false; /* don't expect to be here */
2141 }
Jeff Layton45151482010-07-06 20:43:02 -04002142
Ben Greear3eb9a882010-09-01 17:06:02 -07002143 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2144 return false;
2145
Jeff Layton45151482010-07-06 20:43:02 -04002146 return true;
2147}
2148
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002149static bool
2150match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2151{
Jeff Layton3f618222013-06-12 19:52:14 -05002152 /*
2153 * The select_sectype function should either return the vol->sectype
2154 * that was specified, or "Unspecified" if that sectype was not
2155 * compatible with the given NEGOTIATE request.
2156 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302157 if (server->ops->select_sectype(server, vol->sectype)
2158 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002159 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002160
Jeff Layton3f618222013-06-12 19:52:14 -05002161 /*
2162 * Now check if signing mode is acceptable. No need to check
2163 * global_secflags at this point since if MUST_SIGN is set then
2164 * the server->sign had better be too.
2165 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002166 if (vol->sign && !server->sign)
2167 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002168
2169 return true;
2170}
2171
Jeff Layton9fa114f2012-11-26 11:09:57 -05002172static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002173{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002174 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2175
Jeff Laytona0b3df52013-05-24 07:40:59 -04002176 if (vol->nosharesock)
2177 return 0;
2178
Steve French9764c022017-09-17 10:41:35 -05002179 /* BB update this for smb3any and default case */
Jeff Layton23db65f2012-05-15 12:20:51 -04002180 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2181 return 0;
2182
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002183 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2184 return 0;
2185
2186 if (!match_address(server, addr,
2187 (struct sockaddr *)&vol->srcaddr))
2188 return 0;
2189
2190 if (!match_port(server, addr))
2191 return 0;
2192
2193 if (!match_security(server, vol))
2194 return 0;
2195
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002196 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002197 return 0;
2198
Long Li8339dd32017-11-07 01:54:55 -07002199 if (server->rdma != vol->rdma)
2200 return 0;
2201
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002202 return 1;
2203}
2204
Jeff Layton45151482010-07-06 20:43:02 -04002205static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002206cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002207{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002208 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302210 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002211 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002212 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002213 continue;
2214
Jeff Laytone7ddee92008-11-14 13:44:38 -05002215 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302216 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002217 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002218 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302220 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 return NULL;
2222}
2223
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002224void
2225cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002227 struct task_struct *task;
2228
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302229 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002230 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302231 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002232 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002234
Rob Landleyf1d0c992011-01-22 15:44:05 -06002235 put_net(cifs_net_ns(server));
2236
Jeff Laytone7ddee92008-11-14 13:44:38 -05002237 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302238 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002239
Jeff Laytonc74093b2011-01-11 07:24:23 -05002240 cancel_delayed_work_sync(&server->echo);
2241
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002242 if (from_reconnect)
2243 /*
2244 * Avoid deadlock here: reconnect work calls
2245 * cifs_put_tcp_session() at its end. Need to be sure
2246 * that reconnect work does nothing with server pointer after
2247 * that step.
2248 */
2249 cancel_delayed_work(&server->reconnect);
2250 else
2251 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002252
Jeff Laytone7ddee92008-11-14 13:44:38 -05002253 spin_lock(&GlobalMid_Lock);
2254 server->tcpStatus = CifsExiting;
2255 spin_unlock(&GlobalMid_Lock);
2256
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002257 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302258 cifs_fscache_release_client_cookie(server);
2259
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002260 kfree(server->session_key.response);
2261 server->session_key.response = NULL;
2262 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002263
2264 task = xchg(&server->tsk, NULL);
2265 if (task)
2266 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267}
2268
Jeff Layton63c038c2008-12-01 18:41:46 -05002269static struct TCP_Server_Info *
2270cifs_get_tcp_session(struct smb_vol *volume_info)
2271{
2272 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002273 int rc;
2274
Joe Perchesf96637b2013-05-04 22:12:25 -05002275 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002276
2277 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002278 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002279 if (tcp_ses)
2280 return tcp_ses;
2281
2282 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2283 if (!tcp_ses) {
2284 rc = -ENOMEM;
2285 goto out_err;
2286 }
2287
Jeff Layton23db65f2012-05-15 12:20:51 -04002288 tcp_ses->ops = volume_info->ops;
2289 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002290 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002291 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2292 if (IS_ERR(tcp_ses->hostname)) {
2293 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002294 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002295 }
2296
2297 tcp_ses->noblocksnd = volume_info->noblocksnd;
2298 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002299 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002300 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002301 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002302 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002303 init_waitqueue_head(&tcp_ses->response_q);
2304 init_waitqueue_head(&tcp_ses->request_q);
2305 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2306 mutex_init(&tcp_ses->srv_mutex);
2307 memcpy(tcp_ses->workstation_RFC1001_name,
2308 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2309 memcpy(tcp_ses->server_RFC1001_name,
2310 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002311 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002312 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002313 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002314 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002315 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2316 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002317 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002318 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2319 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002320 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2321 sizeof(tcp_ses->srcaddr));
2322 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2323 sizeof(tcp_ses->dstaddr));
Steve Frenchfa70b872016-09-22 00:39:34 -05002324 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002325 /*
2326 * at this point we are the only ones with the pointer
2327 * to the struct since the kernel thread not created yet
2328 * no need to spinlock this init of tcpStatus or srv_count
2329 */
2330 tcp_ses->tcpStatus = CifsNew;
2331 ++tcp_ses->srv_count;
2332
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002333 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2334 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2335 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2336 else
2337 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002338 if (tcp_ses->rdma) {
2339#ifndef CONFIG_CIFS_SMB_DIRECT
2340 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2341 rc = -ENOENT;
2342 goto out_err_crypto_release;
2343#endif
2344 tcp_ses->smbd_conn = smbd_get_connection(
2345 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2346 if (tcp_ses->smbd_conn) {
2347 cifs_dbg(VFS, "RDMA transport established\n");
2348 rc = 0;
2349 goto smbd_connected;
2350 } else {
2351 rc = -ENOENT;
2352 goto out_err_crypto_release;
2353 }
2354 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002355 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002356 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002357 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002358 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002359 }
Long Li2f894642017-11-22 17:38:34 -07002360smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002361 /*
2362 * since we're in a cifs function already, we know that
2363 * this will succeed. No need for try_module_get().
2364 */
2365 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002366 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002367 tcp_ses, "cifsd");
2368 if (IS_ERR(tcp_ses->tsk)) {
2369 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002370 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002371 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002372 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002373 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002374 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002375
2376 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302377 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002378 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302379 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002380
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302381 cifs_fscache_get_client_cookie(tcp_ses);
2382
Jeff Laytonc74093b2011-01-11 07:24:23 -05002383 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002384 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002385
Jeff Layton63c038c2008-12-01 18:41:46 -05002386 return tcp_ses;
2387
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002388out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002389 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002390
Rob Landleyf1d0c992011-01-22 15:44:05 -06002391 put_net(cifs_net_ns(tcp_ses));
2392
Jeff Layton63c038c2008-12-01 18:41:46 -05002393out_err:
2394 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002395 if (!IS_ERR(tcp_ses->hostname))
2396 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002397 if (tcp_ses->ssocket)
2398 sock_release(tcp_ses->ssocket);
2399 kfree(tcp_ses);
2400 }
2401 return ERR_PTR(rc);
2402}
2403
Steve French96daf2b2011-05-27 04:34:02 +00002404static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002405{
Jeff Layton3f618222013-06-12 19:52:14 -05002406 if (vol->sectype != Unspecified &&
2407 vol->sectype != ses->sectype)
2408 return 0;
2409
2410 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002411 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002412 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002413 return 0;
2414 break;
2415 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002416 /* NULL username means anonymous session */
2417 if (ses->user_name == NULL) {
2418 if (!vol->nullauth)
2419 return 0;
2420 break;
2421 }
2422
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002423 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002424 if (strncmp(ses->user_name,
2425 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002426 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002427 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002428 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002429 ses->password != NULL &&
2430 strncmp(ses->password,
2431 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002432 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002433 return 0;
2434 }
2435 return 1;
2436}
2437
Aurelien Aptelb327a712018-01-24 13:46:10 +01002438/**
2439 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2440 *
2441 * A new IPC connection is made and stored in the session
2442 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2443 */
2444static int
2445cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2446{
2447 int rc = 0, xid;
2448 struct cifs_tcon *tcon;
2449 struct nls_table *nls_codepage;
2450 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2451 bool seal = false;
2452
2453 /*
2454 * If the mount request that resulted in the creation of the
2455 * session requires encryption, force IPC to be encrypted too.
2456 */
2457 if (volume_info->seal) {
2458 if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
2459 seal = true;
2460 else {
2461 cifs_dbg(VFS,
2462 "IPC: server doesn't support encryption\n");
2463 return -EOPNOTSUPP;
2464 }
2465 }
2466
2467 tcon = tconInfoAlloc();
2468 if (tcon == NULL)
2469 return -ENOMEM;
2470
2471 snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->serverName);
2472
2473 /* cannot fail */
2474 nls_codepage = load_nls_default();
2475
2476 xid = get_xid();
2477 tcon->ses = ses;
2478 tcon->ipc = true;
2479 tcon->seal = seal;
2480 rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
2481 free_xid(xid);
2482
2483 if (rc) {
2484 cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
2485 tconInfoFree(tcon);
2486 goto out;
2487 }
2488
2489 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2490
2491 ses->tcon_ipc = tcon;
2492out:
2493 unload_nls(nls_codepage);
2494 return rc;
2495}
2496
2497/**
2498 * cifs_free_ipc - helper to release the session IPC tcon
2499 *
2500 * Needs to be called everytime a session is destroyed
2501 */
2502static int
2503cifs_free_ipc(struct cifs_ses *ses)
2504{
2505 int rc = 0, xid;
2506 struct cifs_tcon *tcon = ses->tcon_ipc;
2507
2508 if (tcon == NULL)
2509 return 0;
2510
2511 if (ses->server->ops->tree_disconnect) {
2512 xid = get_xid();
2513 rc = ses->server->ops->tree_disconnect(xid, tcon);
2514 free_xid(xid);
2515 }
2516
2517 if (rc)
2518 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
2519
2520 tconInfoFree(tcon);
2521 ses->tcon_ipc = NULL;
2522 return rc;
2523}
2524
Steve French96daf2b2011-05-27 04:34:02 +00002525static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002526cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527{
Steve French96daf2b2011-05-27 04:34:02 +00002528 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302530 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002531 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002532 if (ses->status == CifsExiting)
2533 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002534 if (!match_session(ses, vol))
2535 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002536 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302537 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002538 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302540 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 return NULL;
2542}
2543
Jeff Layton14fbf502008-11-14 13:53:46 -05002544static void
Steve French96daf2b2011-05-27 04:34:02 +00002545cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002546{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002547 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002548 struct TCP_Server_Info *server = ses->server;
2549
Joe Perchesf96637b2013-05-04 22:12:25 -05002550 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002551
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302552 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002553 if (ses->status == CifsExiting) {
2554 spin_unlock(&cifs_tcp_ses_lock);
2555 return;
2556 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002557 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302558 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002559 return;
2560 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002561 if (ses->status == CifsGood)
2562 ses->status = CifsExiting;
2563 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002564
Aurelien Aptelb327a712018-01-24 13:46:10 +01002565 cifs_free_ipc(ses);
2566
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002567 if (ses->status == CifsExiting && server->ops->logoff) {
2568 xid = get_xid();
2569 rc = server->ops->logoff(xid, ses);
2570 if (rc)
2571 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2572 __func__, rc);
2573 _free_xid(xid);
2574 }
2575
2576 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002577 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302578 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002579
Jeff Layton14fbf502008-11-14 13:53:46 -05002580 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002581 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05002582}
2583
Jeff Layton8a8798a2012-01-17 16:09:15 -05002584#ifdef CONFIG_KEYS
2585
Chen Gang057d6332013-07-19 09:01:36 +08002586/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2587#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002588
2589/* Populate username and pw fields from keyring if possible */
2590static int
2591cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2592{
2593 int rc = 0;
David Howells146aa8b2015-10-21 14:04:48 +01002594 const char *delim, *payload;
2595 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002596 ssize_t len;
2597 struct key *key;
2598 struct TCP_Server_Info *server = ses->server;
2599 struct sockaddr_in *sa;
2600 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01002601 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002602
2603 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2604 if (!desc)
2605 return -ENOMEM;
2606
2607 /* try to find an address key first */
2608 switch (server->dstaddr.ss_family) {
2609 case AF_INET:
2610 sa = (struct sockaddr_in *)&server->dstaddr;
2611 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2612 break;
2613 case AF_INET6:
2614 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2615 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2616 break;
2617 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002618 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2619 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002620 rc = -EINVAL;
2621 goto out_err;
2622 }
2623
Joe Perchesf96637b2013-05-04 22:12:25 -05002624 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002625 key = request_key(&key_type_logon, desc, "");
2626 if (IS_ERR(key)) {
2627 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002628 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002629 rc = PTR_ERR(key);
2630 goto out_err;
2631 }
2632
2633 /* didn't work, try to find a domain key */
2634 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002635 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002636 key = request_key(&key_type_logon, desc, "");
2637 if (IS_ERR(key)) {
2638 rc = PTR_ERR(key);
2639 goto out_err;
2640 }
2641 }
2642
2643 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00002644 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002645 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002646 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002647 goto out_key_put;
2648 }
2649
2650 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01002651 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002652 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002653 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002654 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002655 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2656 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002657 rc = -EINVAL;
2658 goto out_key_put;
2659 }
2660
2661 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002662 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002663 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2664 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002665 rc = -EINVAL;
2666 goto out_key_put;
2667 }
2668
2669 vol->username = kstrndup(payload, len, GFP_KERNEL);
2670 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002671 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2672 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002673 rc = -ENOMEM;
2674 goto out_key_put;
2675 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002676 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002677
2678 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002679 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002680 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002681 rc = -EINVAL;
2682 kfree(vol->username);
2683 vol->username = NULL;
2684 goto out_key_put;
2685 }
2686
2687 ++delim;
2688 vol->password = kstrndup(delim, len, GFP_KERNEL);
2689 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002690 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2691 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002692 rc = -ENOMEM;
2693 kfree(vol->username);
2694 vol->username = NULL;
2695 goto out_key_put;
2696 }
2697
2698out_key_put:
2699 up_read(&key->sem);
2700 key_put(key);
2701out_err:
2702 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002703 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002704 return rc;
2705}
2706#else /* ! CONFIG_KEYS */
2707static inline int
2708cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2709 struct cifs_ses *ses __attribute__((unused)))
2710{
2711 return -ENOSYS;
2712}
2713#endif /* CONFIG_KEYS */
2714
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002715/**
2716 * cifs_get_smb_ses - get a session matching @volume_info data from @server
2717 *
2718 * This function assumes it is being called from cifs_mount() where we
2719 * already got a server reference (server refcount +1). See
2720 * cifs_get_tcon() for refcount explanations.
2721 */
Steve French96daf2b2011-05-27 04:34:02 +00002722static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002723cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2724{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002725 int rc = -ENOMEM;
2726 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002727 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002728 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2729 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002730
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002731 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002732
Jeff Layton4ff67b72010-07-06 20:43:02 -04002733 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002734 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002735 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2736 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002737
Jeff Layton36988c72010-04-24 07:57:43 -04002738 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002739 rc = cifs_negotiate_protocol(xid, ses);
2740 if (rc) {
2741 mutex_unlock(&ses->session_mutex);
2742 /* problem -- put our ses reference */
2743 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002744 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002745 return ERR_PTR(rc);
2746 }
Jeff Layton36988c72010-04-24 07:57:43 -04002747 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002748 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002749 rc = cifs_setup_session(xid, ses,
2750 volume_info->local_nls);
2751 if (rc) {
2752 mutex_unlock(&ses->session_mutex);
2753 /* problem -- put our reference */
2754 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002755 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002756 return ERR_PTR(rc);
2757 }
2758 }
2759 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002760
2761 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002762 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002763 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002764 return ses;
2765 }
2766
Joe Perchesf96637b2013-05-04 22:12:25 -05002767 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002768 ses = sesInfoAlloc();
2769 if (ses == NULL)
2770 goto get_ses_fail;
2771
2772 /* new SMB session uses our server ref */
2773 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002774 if (server->dstaddr.ss_family == AF_INET6)
2775 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002776 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002777 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002778
Steve French8727c8a2011-02-25 01:11:56 -06002779 if (volume_info->username) {
2780 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2781 if (!ses->user_name)
2782 goto get_ses_fail;
2783 }
Jeff Layton36988c72010-04-24 07:57:43 -04002784
2785 /* volume_info->password freed at unmount */
2786 if (volume_info->password) {
2787 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2788 if (!ses->password)
2789 goto get_ses_fail;
2790 }
2791 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002792 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2793 if (!ses->domainName)
2794 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002795 }
Germano Percossi39566442016-12-15 12:31:18 +05302796 if (volume_info->domainauto)
2797 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002798 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002799 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002800
Jeff Layton28e11bd2013-05-26 07:01:00 -04002801 ses->sectype = volume_info->sectype;
2802 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04002803
2804 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002805 rc = cifs_negotiate_protocol(xid, ses);
2806 if (!rc)
2807 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002808 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002809 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002810 goto get_ses_fail;
2811
2812 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302813 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002814 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302815 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002816
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002817 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002818
2819 cifs_setup_ipc(ses, volume_info);
2820
Jeff Layton36988c72010-04-24 07:57:43 -04002821 return ses;
2822
2823get_ses_fail:
2824 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002825 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002826 return ERR_PTR(rc);
2827}
2828
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002829static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002830{
2831 if (tcon->tidStatus == CifsExiting)
2832 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002833 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002834 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002835 if (tcon->seal != volume_info->seal)
2836 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002837 if (tcon->snapshot_time != volume_info->snapshot_time)
2838 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002839 return 1;
2840}
2841
Steve French96daf2b2011-05-27 04:34:02 +00002842static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06002843cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844{
2845 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002846 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302848 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002849 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002850 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002851 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002852 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002853 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302854 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 return tcon;
2856 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302857 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858 return NULL;
2859}
2860
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002861void
Steve French96daf2b2011-05-27 04:34:02 +00002862cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002863{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002864 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01002865 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002866
Aurelien Aptelb327a712018-01-24 13:46:10 +01002867 /*
2868 * IPC tcon share the lifetime of their session and are
2869 * destroyed in the session put function
2870 */
2871 if (tcon == NULL || tcon->ipc)
2872 return;
2873
2874 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05002875 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302876 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002877 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302878 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002879 return;
2880 }
2881
2882 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302883 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002884
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002885 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002886 if (ses->server->ops->tree_disconnect)
2887 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002888 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002889
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302890 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002891 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002892 cifs_put_smb_ses(ses);
2893}
2894
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002895/**
2896 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
2897 *
2898 * - tcon refcount is the number of mount points using the tcon.
2899 * - ses refcount is the number of tcon using the session.
2900 *
2901 * 1. This function assumes it is being called from cifs_mount() where
2902 * we already got a session reference (ses refcount +1).
2903 *
2904 * 2. Since we're in the context of adding a mount point, the end
2905 * result should be either:
2906 *
2907 * a) a new tcon already allocated with refcount=1 (1 mount point) and
2908 * its session refcount incremented (1 new tcon). This +1 was
2909 * already done in (1).
2910 *
2911 * b) an existing tcon with refcount+1 (add a mount point to it) and
2912 * identical ses refcount (no new tcon). Because of (1) we need to
2913 * decrement the ses refcount.
2914 */
Steve French96daf2b2011-05-27 04:34:02 +00002915static struct cifs_tcon *
2916cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002917{
2918 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002919 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002920
Steve French8b217fe2016-11-11 22:36:20 -06002921 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002922 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002923 /*
2924 * tcon has refcount already incremented but we need to
2925 * decrement extra ses reference gotten by caller (case b)
2926 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002927 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002928 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002929 return tcon;
2930 }
2931
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002932 if (!ses->server->ops->tree_connect) {
2933 rc = -ENOSYS;
2934 goto out_fail;
2935 }
2936
Jeff Laytond00c28d2010-04-24 07:57:44 -04002937 tcon = tconInfoAlloc();
2938 if (tcon == NULL) {
2939 rc = -ENOMEM;
2940 goto out_fail;
2941 }
2942
Steve French8b217fe2016-11-11 22:36:20 -06002943 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06002944 if (ses->server->vals->protocol_id == 0) {
2945 cifs_dbg(VFS,
2946 "Use SMB2 or later for snapshot mount option\n");
2947 rc = -EOPNOTSUPP;
2948 goto out_fail;
2949 } else
2950 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06002951 }
2952
Jeff Laytond00c28d2010-04-24 07:57:44 -04002953 tcon->ses = ses;
2954 if (volume_info->password) {
2955 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2956 if (!tcon->password) {
2957 rc = -ENOMEM;
2958 goto out_fail;
2959 }
2960 }
2961
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002962 /*
2963 * BB Do we need to wrap session_mutex around this TCon call and Unix
2964 * SetFS as we do on SessSetup and reconnect?
2965 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002966 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002967 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
2968 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002969 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05002970 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002971 if (rc)
2972 goto out_fail;
2973
2974 if (volume_info->nodfs) {
2975 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002976 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002977 }
Steve Frenchb618f002015-11-03 09:15:03 -06002978 tcon->use_persistent = false;
2979 /* check if SMB2 or later, CIFS does not support persistent handles */
2980 if (volume_info->persistent) {
2981 if (ses->server->vals->protocol_id == 0) {
2982 cifs_dbg(VFS,
2983 "SMB3 or later required for persistent handles\n");
2984 rc = -EOPNOTSUPP;
2985 goto out_fail;
2986 } else if (ses->server->capabilities &
2987 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2988 tcon->use_persistent = true;
2989 else /* persistent handles requested but not supported */ {
2990 cifs_dbg(VFS,
2991 "Persistent handles not supported on share\n");
2992 rc = -EOPNOTSUPP;
2993 goto out_fail;
2994 }
2995 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
2996 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2997 && (volume_info->nopersistent == false)) {
2998 cifs_dbg(FYI, "enabling persistent handles\n");
2999 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003000 } else if (volume_info->resilient) {
3001 if (ses->server->vals->protocol_id == 0) {
3002 cifs_dbg(VFS,
3003 "SMB2.1 or later required for resilient handles\n");
3004 rc = -EOPNOTSUPP;
3005 goto out_fail;
3006 }
3007 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003008 }
3009
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003010 if (volume_info->seal) {
3011 if (ses->server->vals->protocol_id == 0) {
3012 cifs_dbg(VFS,
3013 "SMB3 or later required for encryption\n");
3014 rc = -EOPNOTSUPP;
3015 goto out_fail;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003016 } else if (tcon->ses->server->capabilities &
3017 SMB2_GLOBAL_CAP_ENCRYPTION)
3018 tcon->seal = true;
3019 else {
3020 cifs_dbg(VFS, "Encryption is not supported on share\n");
3021 rc = -EOPNOTSUPP;
3022 goto out_fail;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003023 }
3024 }
3025
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003026 /*
3027 * We can have only one retry value for a connection to a share so for
3028 * resources mounted more than once to the same server share the last
3029 * value passed in for the retry flag is used.
3030 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003031 tcon->retry = volume_info->retry;
3032 tcon->nocase = volume_info->nocase;
3033 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003034 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003035
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303036 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003037 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303038 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003039
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303040 cifs_fscache_get_super_cookie(tcon);
3041
Jeff Laytond00c28d2010-04-24 07:57:44 -04003042 return tcon;
3043
3044out_fail:
3045 tconInfoFree(tcon);
3046 return ERR_PTR(rc);
3047}
3048
Jeff Layton9d002df2010-10-06 19:51:11 -04003049void
3050cifs_put_tlink(struct tcon_link *tlink)
3051{
3052 if (!tlink || IS_ERR(tlink))
3053 return;
3054
3055 if (!atomic_dec_and_test(&tlink->tl_count) ||
3056 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3057 tlink->tl_time = jiffies;
3058 return;
3059 }
3060
3061 if (!IS_ERR(tlink_tcon(tlink)))
3062 cifs_put_tcon(tlink_tcon(tlink));
3063 kfree(tlink);
3064 return;
3065}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003066
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003067static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04003068cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
3069{
3070 return cifs_sb->master_tlink;
3071}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003072
3073static int
3074compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3075{
3076 struct cifs_sb_info *old = CIFS_SB(sb);
3077 struct cifs_sb_info *new = mnt_data->cifs_sb;
3078
3079 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3080 return 0;
3081
3082 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
3083 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
3084 return 0;
3085
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003086 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003087 * We want to share sb only if we don't specify an r/wsize or
3088 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003089 */
3090 if (new->wsize && new->wsize < old->wsize)
3091 return 0;
3092
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003093 if (new->rsize && new->rsize < old->rsize)
3094 return 0;
3095
Eric W. Biederman1f682332013-02-06 01:20:20 -08003096 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003097 return 0;
3098
3099 if (old->mnt_file_mode != new->mnt_file_mode ||
3100 old->mnt_dir_mode != new->mnt_dir_mode)
3101 return 0;
3102
3103 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3104 return 0;
3105
3106 if (old->actimeo != new->actimeo)
3107 return 0;
3108
3109 return 1;
3110}
3111
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003112static int
3113match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3114{
3115 struct cifs_sb_info *old = CIFS_SB(sb);
3116 struct cifs_sb_info *new = mnt_data->cifs_sb;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003117 bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3118 bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003119
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003120 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003121 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003122 else if (!old_set && !new_set)
3123 return 1;
3124
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003125 return 0;
3126}
3127
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003128int
3129cifs_match_super(struct super_block *sb, void *data)
3130{
3131 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3132 struct smb_vol *volume_info;
3133 struct cifs_sb_info *cifs_sb;
3134 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003135 struct cifs_ses *ses;
3136 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003137 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003138 int rc = 0;
3139
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003140 spin_lock(&cifs_tcp_ses_lock);
3141 cifs_sb = CIFS_SB(sb);
3142 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3143 if (IS_ERR(tlink)) {
3144 spin_unlock(&cifs_tcp_ses_lock);
3145 return rc;
3146 }
3147 tcon = tlink_tcon(tlink);
3148 ses = tcon->ses;
3149 tcp_srv = ses->server;
3150
3151 volume_info = mnt_data->vol;
3152
Jeff Layton9fa114f2012-11-26 11:09:57 -05003153 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003154 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003155 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003156 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003157 rc = 0;
3158 goto out;
3159 }
3160
3161 rc = compare_mount_options(sb, mnt_data);
3162out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003163 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003164 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003165 return rc;
3166}
3167
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003169get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003170 const struct nls_table *nls_codepage, unsigned int *num_referrals,
3171 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 int rc = 0;
3174
Aurelien Aptelb327a712018-01-24 13:46:10 +01003175 if (!ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003176 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003178 *num_referrals = 0;
3179 *referrals = NULL;
3180
Aurelien Aptelb327a712018-01-24 13:46:10 +01003181 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
3182 referrals, num_referrals,
3183 nls_codepage, remap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184 return rc;
3185}
3186
Jeff Layton09e50d52008-07-23 10:11:19 -04003187#ifdef CONFIG_DEBUG_LOCK_ALLOC
3188static struct lock_class_key cifs_key[2];
3189static struct lock_class_key cifs_slock_key[2];
3190
3191static inline void
3192cifs_reclassify_socket4(struct socket *sock)
3193{
3194 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003195 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003196 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3197 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3198}
3199
3200static inline void
3201cifs_reclassify_socket6(struct socket *sock)
3202{
3203 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003204 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003205 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3206 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3207}
3208#else
3209static inline void
3210cifs_reclassify_socket4(struct socket *sock)
3211{
3212}
3213
3214static inline void
3215cifs_reclassify_socket6(struct socket *sock)
3216{
3217}
3218#endif
3219
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003221static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222{
Steve French50c2f752007-07-13 00:33:32 +00003223 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
Steve French50c2f752007-07-13 00:33:32 +00003225 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 /* mask a nibble at a time and encode */
3227 target[j] = 'A' + (0x0F & (source[i] >> 4));
3228 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003229 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230 }
3231
3232}
3233
Ben Greear3eb9a882010-09-01 17:06:02 -07003234static int
3235bind_socket(struct TCP_Server_Info *server)
3236{
3237 int rc = 0;
3238 if (server->srcaddr.ss_family != AF_UNSPEC) {
3239 /* Bind to the specified local IP address */
3240 struct socket *socket = server->ssocket;
3241 rc = socket->ops->bind(socket,
3242 (struct sockaddr *) &server->srcaddr,
3243 sizeof(server->srcaddr));
3244 if (rc < 0) {
3245 struct sockaddr_in *saddr4;
3246 struct sockaddr_in6 *saddr6;
3247 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3248 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3249 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05003250 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3251 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003252 else
Joe Perchesf96637b2013-05-04 22:12:25 -05003253 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3254 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003255 }
3256 }
3257 return rc;
3258}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
3260static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003261ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262{
3263 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003264 /*
3265 * some servers require RFC1001 sessinit before sending
3266 * negprot - BB check reconnection in case where second
3267 * sessinit is sent but no second negprot
3268 */
3269 struct rfc1002_session_packet *ses_init_buf;
3270 struct smb_hdr *smb_buf;
3271 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3272 GFP_KERNEL);
3273 if (ses_init_buf) {
3274 ses_init_buf->trailer.session_req.called_len = 32;
3275
Colin Ian King997152f2016-01-25 16:25:54 +00003276 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003277 rfc1002mangle(ses_init_buf->trailer.
3278 session_req.called_name,
3279 server->server_RFC1001_name,
3280 RFC1001_NAME_LEN_WITH_NULL);
3281 else
3282 rfc1002mangle(ses_init_buf->trailer.
3283 session_req.called_name,
3284 DEFAULT_CIFS_CALLED_NAME,
3285 RFC1001_NAME_LEN_WITH_NULL);
3286
3287 ses_init_buf->trailer.session_req.calling_len = 32;
3288
3289 /*
3290 * calling name ends in null (byte 16) from old smb
3291 * convention.
3292 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003293 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003294 rfc1002mangle(ses_init_buf->trailer.
3295 session_req.calling_name,
3296 server->workstation_RFC1001_name,
3297 RFC1001_NAME_LEN_WITH_NULL);
3298 else
3299 rfc1002mangle(ses_init_buf->trailer.
3300 session_req.calling_name,
3301 "LINUX_CIFS_CLNT",
3302 RFC1001_NAME_LEN_WITH_NULL);
3303
3304 ses_init_buf->trailer.session_req.scope1 = 0;
3305 ses_init_buf->trailer.session_req.scope2 = 0;
3306 smb_buf = (struct smb_hdr *)ses_init_buf;
3307
3308 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003309 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003310 rc = smb_send(server, smb_buf, 0x44);
3311 kfree(ses_init_buf);
3312 /*
3313 * RFC1001 layer in at least one server
3314 * requires very short break before negprot
3315 * presumably because not expecting negprot
3316 * to follow so fast. This is a simple
3317 * solution that works without
3318 * complicating the code and causes no
3319 * significant slowing down on mount
3320 * for everyone else
3321 */
3322 usleep_range(1000, 2000);
3323 }
3324 /*
3325 * else the negprot may still work without this
3326 * even though malloc failed
3327 */
3328
3329 return rc;
3330}
3331
3332static int
3333generic_ip_connect(struct TCP_Server_Info *server)
3334{
3335 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003336 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003337 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003338 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003339 struct sockaddr *saddr;
3340
3341 saddr = (struct sockaddr *) &server->dstaddr;
3342
3343 if (server->dstaddr.ss_family == AF_INET6) {
3344 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3345 slen = sizeof(struct sockaddr_in6);
3346 sfamily = AF_INET6;
3347 } else {
3348 sport = ((struct sockaddr_in *) saddr)->sin_port;
3349 slen = sizeof(struct sockaddr_in);
3350 sfamily = AF_INET;
3351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003353 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003354 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3355 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003357 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003358 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003361
3362 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003363 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003364 server->ssocket = socket;
3365 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003366 if (sfamily == AF_INET6)
3367 cifs_reclassify_socket6(socket);
3368 else
3369 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 }
3371
Ben Greear3eb9a882010-09-01 17:06:02 -07003372 rc = bind_socket(server);
3373 if (rc < 0)
3374 return rc;
3375
Jeff Laytond5c56052008-12-01 18:42:33 -05003376 /*
3377 * Eventually check for other socket options to change from
3378 * the default. sock_setsockopt not used because it expects
3379 * user space buffer
3380 */
3381 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003382 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003383
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003384 /* make the bufsizes depend on wsize/rsize and max requests */
3385 if (server->noautotune) {
3386 if (socket->sk->sk_sndbuf < (200 * 1024))
3387 socket->sk->sk_sndbuf = 200 * 1024;
3388 if (socket->sk->sk_rcvbuf < (140 * 1024))
3389 socket->sk->sk_rcvbuf = 140 * 1024;
3390 }
3391
Steve French6a5fa2362010-01-01 01:28:43 +00003392 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003393 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003394 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3395 (char *)&val, sizeof(val));
3396 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003397 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3398 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003399 }
3400
Joe Perchesf96637b2013-05-04 22:12:25 -05003401 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003402 socket->sk->sk_sndbuf,
3403 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3404
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003405 rc = socket->ops->connect(socket, saddr, slen, 0);
3406 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003407 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003408 sock_release(socket);
3409 server->ssocket = NULL;
3410 return rc;
3411 }
3412
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003413 if (sport == htons(RFC1001_PORT))
3414 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003415
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 return rc;
3417}
3418
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003419static int
3420ip_connect(struct TCP_Server_Info *server)
3421{
Steve French6da97912011-03-13 18:55:55 +00003422 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003423 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3424 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3425
3426 if (server->dstaddr.ss_family == AF_INET6)
3427 sport = &addr6->sin6_port;
3428 else
3429 sport = &addr->sin_port;
3430
3431 if (*sport == 0) {
3432 int rc;
3433
3434 /* try with 445 port at first */
3435 *sport = htons(CIFS_PORT);
3436
3437 rc = generic_ip_connect(server);
3438 if (rc >= 0)
3439 return rc;
3440
3441 /* if it failed, try with 139 port */
3442 *sport = htons(RFC1001_PORT);
3443 }
3444
3445 return generic_ip_connect(server);
3446}
3447
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003448void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003449 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003450{
3451 /* if we are reconnecting then should we check to see if
3452 * any requested capabilities changed locally e.g. via
3453 * remount but we can not do much about it here
3454 * if they have (even if we could detect it by the following)
3455 * Perhaps we could add a backpointer to array of sb from tcon
3456 * or if we change to make all sb to same share the same
3457 * sb as NFS - then we only have one backpointer to sb.
3458 * What if we wanted to mount the server share twice once with
3459 * and once without posixacls or posix paths? */
3460 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003461
Steve Frenchc18c8422007-07-18 23:21:09 +00003462 if (vol_info && vol_info->no_linux_ext) {
3463 tcon->fsUnixInfo.Capability = 0;
3464 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003465 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003466 return;
3467 } else if (vol_info)
3468 tcon->unix_ext = 1; /* Unix Extensions supported */
3469
3470 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003471 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003472 return;
3473 }
Steve French50c2f752007-07-13 00:33:32 +00003474
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003475 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003476 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003477 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003478 /* check for reconnect case in which we do not
3479 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003480 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003481 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003482 originally at mount time */
3483 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3484 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003485 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3486 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003487 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003488 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003489 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003490 cifs_dbg(VFS, "possible reconnect error\n");
3491 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003492 }
Steve French8af18972007-02-14 04:42:51 +00003493 }
Steve French50c2f752007-07-13 00:33:32 +00003494
Steve French6848b732011-05-26 18:38:54 +00003495 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003496 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003497
Steve French8af18972007-02-14 04:42:51 +00003498 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003499 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003500 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003501 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003502 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003503 if (cifs_sb)
3504 cifs_sb->mnt_cifs_flags |=
3505 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003506 }
3507
Steve French75865f8c2007-06-24 18:30:48 +00003508 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003509 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003510 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003511 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003512 if (cifs_sb)
3513 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003514 CIFS_MOUNT_POSIX_PATHS;
3515 }
Steve French50c2f752007-07-13 00:33:32 +00003516
Joe Perchesf96637b2013-05-04 22:12:25 -05003517 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003518#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003519 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003520 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003521 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003522 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003523 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003524 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003525 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003526 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003527 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003528 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003529 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003530 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003531 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003532 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003533 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003534 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003535 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003536 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003537#endif /* CIFS_DEBUG2 */
3538 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003539 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003540 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003541 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003542 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 +00003543
Steve French8af18972007-02-14 04:42:51 +00003544 }
3545 }
3546}
3547
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003548int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003549 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003550{
Jeff Layton2de970f2010-10-06 19:51:12 -04003551 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3552
Al Viro2ced6f62011-06-17 09:20:04 -04003553 spin_lock_init(&cifs_sb->tlink_tree_lock);
3554 cifs_sb->tlink_tree = RB_ROOT;
3555
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003556 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003557 * Temporarily set r/wsize for matching superblock. If we end up using
3558 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003559 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003560 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003561 cifs_sb->wsize = pvolume_info->wsize;
3562
Steve French3b795212008-11-13 19:45:32 +00003563 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3564 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3565 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3566 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003567 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3568 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003569
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303570 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003571 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303572
Steve French3b795212008-11-13 19:45:32 +00003573 if (pvolume_info->noperm)
3574 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3575 if (pvolume_info->setuids)
3576 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05003577 if (pvolume_info->setuidfromacl)
3578 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00003579 if (pvolume_info->server_ino)
3580 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3581 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003582 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3583 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003584 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3585 if (pvolume_info->no_xattr)
3586 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3587 if (pvolume_info->sfu_emul)
3588 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3589 if (pvolume_info->nobrl)
3590 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003591 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003592 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003593 if (pvolume_info->mand_lock)
3594 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003595 if (pvolume_info->rwpidforward)
3596 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003597 if (pvolume_info->cifs_acl)
3598 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003599 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003600 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003601 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3602 }
3603 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003604 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003605 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3606 }
Steve French3b795212008-11-13 19:45:32 +00003607 if (pvolume_info->override_uid)
3608 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3609 if (pvolume_info->override_gid)
3610 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3611 if (pvolume_info->dynperm)
3612 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303613 if (pvolume_info->fsc)
3614 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003615 if (pvolume_info->multiuser)
3616 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3617 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003618 if (pvolume_info->strict_io)
3619 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003620 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003621 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003622 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3623 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003624 if (pvolume_info->mfsymlinks) {
3625 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003626 /*
3627 * Our SFU ("Services for Unix" emulation does not allow
3628 * creating symlinks but does allow reading existing SFU
3629 * symlinks (it does allow both creating and reading SFU
3630 * style mknod and FIFOs though). When "mfsymlinks" and
3631 * "sfu" are both enabled at the same time, it allows
3632 * reading both types of symlinks, but will only create
3633 * them with mfsymlinks format. This allows better
3634 * Apple compatibility (probably better for Samba too)
3635 * while still recognizing old Windows style symlinks.
3636 */
3637 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003638 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003639 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003640 }
Steve French3b795212008-11-13 19:45:32 +00003641
3642 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003643 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003644
3645 if (pvolume_info->prepath) {
3646 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
3647 if (cifs_sb->prepath == NULL)
3648 return -ENOMEM;
3649 }
3650
3651 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003652}
3653
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003654static void
3655cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003656{
Sean Finneyb9468452011-04-11 13:19:32 +00003657 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003658 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003659 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003660 kfree(volume_info->domainname);
3661 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003662 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003663}
3664
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003665void
3666cifs_cleanup_volume_info(struct smb_vol *volume_info)
3667{
3668 if (!volume_info)
3669 return;
3670 cleanup_volume_info_contents(volume_info);
3671 kfree(volume_info);
3672}
3673
3674
Steve French2d6d5892009-04-09 00:36:44 +00003675#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003676/*
3677 * cifs_build_path_to_root returns full path to root when we do not have an
3678 * exiting connection (tcon)
3679 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003680static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003681build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003682 const struct cifs_sb_info *cifs_sb)
3683{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003684 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003685 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003686 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003687
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003688 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003689 if (full_path == NULL)
3690 return ERR_PTR(-ENOMEM);
3691
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003692 strncpy(full_path, vol->UNC, unc_len);
3693 pos = full_path + unc_len;
3694
3695 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04003696 *pos = CIFS_DIR_SEP(cifs_sb);
3697 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003698 pos += pplen;
3699 }
3700
3701 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003702 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003703 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003704 return full_path;
3705}
Sean Finneydd613942011-04-11 13:19:30 +00003706
3707/*
3708 * Perform a dfs referral query for a share and (optionally) prefix
3709 *
Sean Finney046462a2011-04-11 13:19:33 +00003710 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3711 * to a string containing updated options for the submount. Otherwise it
3712 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003713 *
3714 * Returns the rc from get_dfs_path to the caller, which can be used to
3715 * determine whether there were referrals.
3716 */
3717static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003718expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003719 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003720 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003721{
3722 int rc;
3723 unsigned int num_referrals = 0;
3724 struct dfs_info3_param *referrals = NULL;
3725 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3726
3727 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3728 if (IS_ERR(full_path))
3729 return PTR_ERR(full_path);
3730
3731 /* For DFS paths, skip the first '\' of the UNC */
3732 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3733
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003734 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05003735 &num_referrals, &referrals, cifs_remap(cifs_sb));
Sean Finneydd613942011-04-11 13:19:30 +00003736
3737 if (!rc && num_referrals > 0) {
3738 char *fake_devname = NULL;
3739
3740 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3741 full_path + 1, referrals,
3742 &fake_devname);
3743
3744 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003745
Sean Finneydd613942011-04-11 13:19:30 +00003746 if (IS_ERR(mdata)) {
3747 rc = PTR_ERR(mdata);
3748 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003749 } else {
3750 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003751 rc = cifs_setup_volume_info(volume_info, mdata,
3752 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003753 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003754 kfree(fake_devname);
3755 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003756 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003757 }
3758 kfree(full_path);
3759 return rc;
3760}
Steve French2d6d5892009-04-09 00:36:44 +00003761#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003762
Jeff Layton04db79b2011-07-06 08:10:38 -04003763static int
3764cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3765 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003767 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003768
Jeff Layton04db79b2011-07-06 08:10:38 -04003769 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3770 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771
Jeff Layton7586b762008-12-01 18:41:49 -05003772 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003773 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05003774 kfree(volume_info->username);
3775 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003776 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05003778 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05003780 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00003781 /* In userspace mount helper we can get user name from alternate
3782 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003783 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 }
3785
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003787 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003788 /* load_nls_default cannot return null */
3789 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003791 volume_info->local_nls = load_nls(volume_info->iocharset);
3792 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003793 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003794 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003795 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 }
3797 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003798
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003799 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003800}
3801
3802struct smb_vol *
3803cifs_get_volume_info(char *mount_data, const char *devname)
3804{
3805 int rc;
3806 struct smb_vol *volume_info;
3807
Jeff Layton6ee95422012-11-26 11:09:57 -05003808 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003809 if (!volume_info)
3810 return ERR_PTR(-ENOMEM);
3811
3812 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3813 if (rc) {
3814 cifs_cleanup_volume_info(volume_info);
3815 volume_info = ERR_PTR(rc);
3816 }
3817
3818 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003819}
3820
Aurelien Aptela6b50582016-05-25 19:59:09 +02003821static int
3822cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
3823 unsigned int xid,
3824 struct cifs_tcon *tcon,
3825 struct cifs_sb_info *cifs_sb,
3826 char *full_path)
3827{
3828 int rc;
3829 char *s;
3830 char sep, tmp;
3831
3832 sep = CIFS_DIR_SEP(cifs_sb);
3833 s = full_path;
3834
3835 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
3836 while (rc == 0) {
3837 /* skip separators */
3838 while (*s == sep)
3839 s++;
3840 if (!*s)
3841 break;
3842 /* next separator */
3843 while (*s && *s != sep)
3844 s++;
3845
3846 /*
3847 * temporarily null-terminate the path at the end of
3848 * the current component
3849 */
3850 tmp = *s;
3851 *s = 0;
3852 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3853 full_path);
3854 *s = tmp;
3855 }
3856 return rc;
3857}
3858
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003859int
Al Viro2c6292a2011-06-17 09:05:48 -04003860cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003861{
Jeff Layton1daaae82012-03-21 06:30:40 -04003862 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003863 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003864 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00003865 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003866 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003867 char *full_path;
3868 struct tcon_link *tlink;
3869#ifdef CONFIG_CIFS_DFS_UPCALL
3870 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003871#endif
Al Virodd854462011-06-17 08:24:42 -04003872
Jeff Layton20547492011-07-09 12:21:07 -04003873#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003874try_mount_again:
3875 /* cleanup activities if we're chasing a referral */
3876 if (referral_walks_count) {
3877 if (tcon)
3878 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003879 else if (ses)
3880 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003881
Sachin Prabhu1dfd18d2015-06-16 16:36:17 +01003882 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
3883
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003884 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003885 }
3886#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003887 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003888 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003889 ses = NULL;
3890 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003891 full_path = NULL;
3892 tlink = NULL;
3893
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003894 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
Jeff Layton63c038c2008-12-01 18:41:46 -05003896 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003897 server = cifs_get_tcp_session(volume_info);
3898 if (IS_ERR(server)) {
3899 rc = PTR_ERR(server);
Jeff Layton63c038c2008-12-01 18:41:46 -05003900 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 }
Steve French141891f2016-09-23 00:44:16 -05003902 if ((volume_info->max_credits < 20) ||
3903 (volume_info->max_credits > 60000))
3904 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
3905 else
3906 server->max_credits = volume_info->max_credits;
Jeff Layton36988c72010-04-24 07:57:43 -04003907 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003908 ses = cifs_get_smb_ses(server, volume_info);
3909 if (IS_ERR(ses)) {
3910 rc = PTR_ERR(ses);
3911 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04003912 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 }
Steve French50c2f752007-07-13 00:33:32 +00003914
Steve Frenchb618f002015-11-03 09:15:03 -06003915 if ((volume_info->persistent == true) && ((ses->server->capabilities &
3916 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
3917 cifs_dbg(VFS, "persistent handles not supported by server\n");
3918 rc = -EOPNOTSUPP;
3919 goto mount_fail_check;
3920 }
Steve French592fafe2015-11-03 10:08:53 -06003921
Jeff Laytond00c28d2010-04-24 07:57:44 -04003922 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003923 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003924 if (IS_ERR(tcon)) {
3925 rc = PTR_ERR(tcon);
3926 tcon = NULL;
Mark Syms40920c22016-11-29 11:36:46 +00003927 if (rc == -EACCES)
3928 goto mount_fail_check;
3929
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003930 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003931 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003932
Steve French6848b732011-05-26 18:38:54 +00003933 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003934 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00003935 /* reset of caps checks mount to see if unix extensions
3936 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003937 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003938 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3939 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3940 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3941 rc = -EACCES;
3942 goto mount_fail_check;
3943 }
3944 } else
3945 tcon->unix_ext = 0; /* server does not support them */
3946
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003947 /* do not care if a following call succeed - informational */
Aurelien Aptelb327a712018-01-24 13:46:10 +01003948 if (!tcon->pipe && server->ops->qfs_tcon)
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003949 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00003950
Pavel Shilovsky24985c52012-09-18 16:20:28 -07003951 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
3952 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003953
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003954remote_path_check:
Sean Finneyc1508ca2011-04-11 13:19:31 +00003955#ifdef CONFIG_CIFS_DFS_UPCALL
3956 /*
3957 * Perform an unconditional check for whether there are DFS
3958 * referrals for this path without prefix, to provide support
3959 * for DFS referrals from w2k8 servers which don't seem to respond
3960 * with PATH_NOT_COVERED to requests that include the prefix.
3961 * Chase the referral if found, otherwise continue normally.
3962 */
3963 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003964 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
3965 false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00003966 if (!refrc) {
3967 referral_walks_count++;
3968 goto try_mount_again;
3969 }
3970 }
3971#endif
3972
Steve Frenchf87d39d2011-05-27 03:50:55 +00003973 /* check if a whole path is not remote */
Jeff Layton70945642011-03-14 13:48:08 -04003974 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003975 if (!server->ops->is_path_accessible) {
3976 rc = -ENOSYS;
3977 goto mount_fail_check;
3978 }
Steve French6d3ea7e2012-11-28 22:34:41 -06003979 /*
3980 * cifs_build_path_to_root works only when we have a valid tcon
3981 */
Sachin Prabhu374402a2016-12-15 12:31:19 +05303982 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon,
3983 tcon->Flags & SMB_SHARE_IS_IN_DFS);
Igor Mammedove4cce942009-02-10 14:10:26 +03003984 if (full_path == NULL) {
3985 rc = -ENOMEM;
3986 goto mount_fail_check;
3987 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003988 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3989 full_path);
Jeff Layton03ceace2010-12-06 21:07:33 -05003990 if (rc != 0 && rc != -EREMOTE) {
Igor Mammedove4cce942009-02-10 14:10:26 +03003991 kfree(full_path);
3992 goto mount_fail_check;
3993 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02003994
Sachin Prabhud1713562016-09-06 13:22:34 +01003995 if (rc != -EREMOTE) {
3996 rc = cifs_are_all_path_components_accessible(server,
Aurelien Aptela6b50582016-05-25 19:59:09 +02003997 xid, tcon, cifs_sb,
3998 full_path);
Sachin Prabhud1713562016-09-06 13:22:34 +01003999 if (rc != 0) {
4000 cifs_dbg(VFS, "cannot query dirs between root and final path, "
4001 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4002 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4003 rc = 0;
4004 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004005 }
Igor Mammedove4cce942009-02-10 14:10:26 +03004006 kfree(full_path);
4007 }
4008
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004009 /* get referral if needed */
4010 if (rc == -EREMOTE) {
Steve Frenchd036f502009-04-03 03:12:08 +00004011#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004012 if (referral_walks_count > MAX_NESTED_LINKS) {
4013 /*
4014 * BB: when we implement proper loop detection,
4015 * we will remove this check. But now we need it
4016 * to prevent an indefinite loop if 'DFS tree' is
4017 * misconfigured (i.e. has loops).
4018 */
4019 rc = -ELOOP;
4020 goto mount_fail_check;
4021 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004022
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004023 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04004024
Sean Finneydd613942011-04-11 13:19:30 +00004025 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004026 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004027 goto try_mount_again;
4028 }
Sean Finneydd613942011-04-11 13:19:30 +00004029 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00004030#else /* No DFS support, return error on mount */
4031 rc = -EOPNOTSUPP;
4032#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004033 }
4034
Jeff Layton9d002df2010-10-06 19:51:11 -04004035 if (rc)
4036 goto mount_fail_check;
4037
4038 /* now, hang the tcon off of the superblock */
4039 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
4040 if (tlink == NULL) {
4041 rc = -ENOMEM;
4042 goto mount_fail_check;
4043 }
4044
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004045 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004046 tlink->tl_tcon = tcon;
4047 tlink->tl_time = jiffies;
4048 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4049 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4050
Jeff Layton413e6612010-10-28 13:33:38 -04004051 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004052 spin_lock(&cifs_sb->tlink_tree_lock);
4053 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4054 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04004055
Jeff Laytonda472fc2012-03-23 14:40:53 -04004056 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004057 TLINK_IDLE_EXPIRE);
4058
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004059mount_fail_check:
4060 /* on error free sesinfo and tcon struct if needed */
4061 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004062 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03004063 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004064 if (tcon)
4065 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004066 else if (ses)
4067 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004068 else
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004069 cifs_put_tcp_session(server, 0);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004070 }
4071
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004072out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004073 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074 return rc;
4075}
4076
Jeff Layton8d1bca32011-06-11 21:17:10 -04004077/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01004078 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04004079 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04004081CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00004082 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 const struct nls_table *nls_codepage)
4084{
4085 struct smb_hdr *smb_buffer;
4086 struct smb_hdr *smb_buffer_response;
4087 TCONX_REQ *pSMB;
4088 TCONX_RSP *pSMBr;
4089 unsigned char *bcc_ptr;
4090 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05004091 int length;
4092 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093
4094 if (ses == NULL)
4095 return -EIO;
4096
4097 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00004098 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00004100
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101 smb_buffer_response = smb_buffer;
4102
4103 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
4104 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07004105
Pavel Shilovsky88257362012-05-23 14:01:59 +04004106 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 smb_buffer->Uid = ses->Suid;
4108 pSMB = (TCONX_REQ *) smb_buffer;
4109 pSMBr = (TCONX_RSP *) smb_buffer_response;
4110
4111 pSMB->AndXCommand = 0xFF;
4112 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01004114 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08004115 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00004116 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08004117 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00004118 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08004119 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004120 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08004121 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
4122 specified as required (when that support is added to
4123 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00004124 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08004125 by Samba (not sure whether other servers allow
4126 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00004127#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04004128 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05004129 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05004130 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00004131 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05004132 SECMODE_PW_ENCRYPT ? true : false,
4133 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00004134 else
4135#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06004136 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05004137 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05004138 if (rc) {
4139 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
4140 __func__, rc);
4141 cifs_buf_release(smb_buffer);
4142 return rc;
4143 }
Steve Frencheeac8042006-01-13 21:34:58 -08004144
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004145 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004146 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00004147 /* must align unicode strings */
4148 *bcc_ptr = 0; /* null byte password */
4149 bcc_ptr++;
4150 }
Steve Frencheeac8042006-01-13 21:34:58 -08004151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152
Jeff Layton38d77c52013-05-26 07:01:00 -04004153 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4155
4156 if (ses->capabilities & CAP_STATUS32) {
4157 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
4158 }
4159 if (ses->capabilities & CAP_DFS) {
4160 smb_buffer->Flags2 |= SMBFLG2_DFS;
4161 }
4162 if (ses->capabilities & CAP_UNICODE) {
4163 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
4164 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06004165 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004166 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004167 (/* server len*/ + 256 /* share len */), nls_codepage);
4168 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 bcc_ptr += 2; /* skip trailing null */
4170 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 strcpy(bcc_ptr, tree);
4172 bcc_ptr += strlen(tree) + 1;
4173 }
4174 strcpy(bcc_ptr, "?????");
4175 bcc_ptr += strlen("?????");
4176 bcc_ptr += 1;
4177 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004178 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4179 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 pSMB->ByteCount = cpu_to_le16(count);
4181
Steve French133672e2007-11-13 22:41:37 +00004182 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004183 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01004186 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004187 bool is_unicode;
4188
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004190 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 tcon->tid = smb_buffer_response->Tid;
4192 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004193 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004194 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004195 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4196 is_unicode = true;
4197 else
4198 is_unicode = false;
4199
Jeff Laytoncc20c032009-04-30 07:16:21 -04004200
Steve French50c2f752007-07-13 00:33:32 +00004201 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004202 if (length == 3) {
4203 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4204 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004205 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01004206 tcon->ipc = true;
4207 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00004208 }
4209 } else if (length == 2) {
4210 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4211 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05004212 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004213 }
4214 }
Steve French50c2f752007-07-13 00:33:32 +00004215 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004216 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05004217 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04004218
4219 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004220 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004221 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004222 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004223 nls_codepage);
4224
Joe Perchesf96637b2013-05-04 22:12:25 -05004225 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004226
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004227 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004228 (smb_buffer_response->WordCount == 7))
4229 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004230 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4231 else
4232 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05004233 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234 }
4235
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004236 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237 return rc;
4238}
4239
Al Viro2e32cf52013-10-03 12:53:37 -04004240static void delayed_free(struct rcu_head *p)
4241{
4242 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
4243 unload_nls(sbi->local_nls);
4244 kfree(sbi);
4245}
4246
Al Viro2a9b9952011-06-17 09:27:16 -04004247void
4248cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249{
Jeff Laytonb647c352010-10-28 11:16:44 -04004250 struct rb_root *root = &cifs_sb->tlink_tree;
4251 struct rb_node *node;
4252 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253
Jeff Layton2de970f2010-10-06 19:51:12 -04004254 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4255
Jeff Laytonb647c352010-10-28 11:16:44 -04004256 spin_lock(&cifs_sb->tlink_tree_lock);
4257 while ((node = rb_first(root))) {
4258 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4259 cifs_get_tlink(tlink);
4260 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4261 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004262
Jeff Laytonb647c352010-10-28 11:16:44 -04004263 spin_unlock(&cifs_sb->tlink_tree_lock);
4264 cifs_put_tlink(tlink);
4265 spin_lock(&cifs_sb->tlink_tree_lock);
4266 }
4267 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004268
Al Virod757d712011-06-17 09:42:43 -04004269 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02004270 kfree(cifs_sb->prepath);
Al Viro2e32cf52013-10-03 12:53:37 -04004271 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00004272}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004274int
4275cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276{
4277 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004278 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004280 if (!server->ops->need_neg || !server->ops->negotiate)
4281 return -ENOSYS;
4282
Jeff Layton198b5682010-04-24 07:57:48 -04004283 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004284 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04004285 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286
Pavel Shilovsky45275782012-05-17 17:53:29 +04004287 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004288
4289 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04004290 if (rc == 0) {
4291 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004292 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004293 server->tcpStatus = CifsGood;
4294 else
4295 rc = -EHOSTDOWN;
4296 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 }
Steve French26b994f2008-08-06 05:11:33 +00004298
Jeff Layton198b5682010-04-24 07:57:48 -04004299 return rc;
4300}
Steve French26b994f2008-08-06 05:11:33 +00004301
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004302int
4303cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
4304 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04004305{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004306 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04004307 struct TCP_Server_Info *server = ses->server;
4308
Jeff Layton198b5682010-04-24 07:57:48 -04004309 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004310 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004311 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00004312
Joe Perchesf96637b2013-05-04 22:12:25 -05004313 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00004314 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004315
Shu Wangf5c4ba82017-09-08 18:48:33 +08004316 if (ses->auth_key.response) {
Steve French2a182872018-03-29 12:16:34 -05004317 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
Shu Wangf5c4ba82017-09-08 18:48:33 +08004318 ses->auth_key.response);
4319 kfree(ses->auth_key.response);
4320 ses->auth_key.response = NULL;
4321 ses->auth_key.len = 0;
4322 }
4323
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004324 if (server->ops->sess_setup)
4325 rc = server->ops->sess_setup(xid, ses, nls_info);
4326
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05004327 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05004328 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004329
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 return rc;
4331}
4332
Jeff Layton8a8798a2012-01-17 16:09:15 -05004333static int
4334cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4335{
Jeff Layton3f618222013-06-12 19:52:14 -05004336 vol->sectype = ses->sectype;
4337
4338 /* krb5 is special, since we don't need username or pw */
4339 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05004340 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05004341
4342 return cifs_set_cifscreds(vol, ses);
4343}
4344
Steve French96daf2b2011-05-27 04:34:02 +00004345static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004346cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04004347{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004348 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004349 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4350 struct cifs_ses *ses;
4351 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004352 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004353
4354 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004355 if (vol_info == NULL)
4356 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004357
Jeff Layton9d002df2010-10-06 19:51:11 -04004358 vol_info->local_nls = cifs_sb->local_nls;
4359 vol_info->linux_uid = fsuid;
4360 vol_info->cred_uid = fsuid;
4361 vol_info->UNC = master_tcon->treeName;
4362 vol_info->retry = master_tcon->retry;
4363 vol_info->nocase = master_tcon->nocase;
4364 vol_info->local_lease = master_tcon->local_lease;
4365 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004366 vol_info->sectype = master_tcon->ses->sectype;
4367 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004368
Jeff Layton8a8798a2012-01-17 16:09:15 -05004369 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4370 if (rc) {
4371 tcon = ERR_PTR(rc);
4372 goto out;
4373 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004374
4375 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304376 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004377 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304378 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004379
4380 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4381 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004382 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004383 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04004384 goto out;
4385 }
4386
4387 tcon = cifs_get_tcon(ses, vol_info);
4388 if (IS_ERR(tcon)) {
4389 cifs_put_smb_ses(ses);
4390 goto out;
4391 }
4392
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004393 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004394 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4395out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004396 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01004397 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004398 kfree(vol_info);
4399
4400 return tcon;
4401}
4402
Steve French96daf2b2011-05-27 04:34:02 +00004403struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004404cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4405{
4406 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4407}
4408
Jeff Laytonb647c352010-10-28 11:16:44 -04004409/* find and return a tlink with given uid */
4410static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004411tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04004412{
4413 struct rb_node *node = root->rb_node;
4414 struct tcon_link *tlink;
4415
4416 while (node) {
4417 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4418
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004419 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004420 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004421 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004422 node = node->rb_right;
4423 else
4424 return tlink;
4425 }
4426 return NULL;
4427}
4428
4429/* insert a tcon_link into the tree */
4430static void
4431tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4432{
4433 struct rb_node **new = &(root->rb_node), *parent = NULL;
4434 struct tcon_link *tlink;
4435
4436 while (*new) {
4437 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4438 parent = *new;
4439
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004440 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004441 new = &((*new)->rb_left);
4442 else
4443 new = &((*new)->rb_right);
4444 }
4445
4446 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4447 rb_insert_color(&new_tlink->tl_rbnode, root);
4448}
4449
Jeff Layton9d002df2010-10-06 19:51:11 -04004450/*
4451 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4452 * current task.
4453 *
4454 * If the superblock doesn't refer to a multiuser mount, then just return
4455 * the master tcon for the mount.
4456 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304457 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004458 * exists, then check to see if it's pending construction. If it is then wait
4459 * for construction to complete. Once it's no longer pending, check to see if
4460 * it failed and either return an error or retry construction, depending on
4461 * the timeout.
4462 *
4463 * If one doesn't exist then insert a new tcon_link struct into the tree and
4464 * try to construct a new one.
4465 */
4466struct tcon_link *
4467cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4468{
4469 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004470 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004471 struct tcon_link *tlink, *newtlink;
4472
4473 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4474 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4475
4476 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004477 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004478 if (tlink)
4479 cifs_get_tlink(tlink);
4480 spin_unlock(&cifs_sb->tlink_tree_lock);
4481
4482 if (tlink == NULL) {
4483 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4484 if (newtlink == NULL)
4485 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004486 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004487 newtlink->tl_tcon = ERR_PTR(-EACCES);
4488 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4489 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4490 cifs_get_tlink(newtlink);
4491
Jeff Layton9d002df2010-10-06 19:51:11 -04004492 spin_lock(&cifs_sb->tlink_tree_lock);
4493 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004494 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004495 if (tlink) {
4496 cifs_get_tlink(tlink);
4497 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004498 kfree(newtlink);
4499 goto wait_for_construction;
4500 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004501 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004502 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4503 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004504 } else {
4505wait_for_construction:
4506 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04004507 TASK_INTERRUPTIBLE);
4508 if (ret) {
4509 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10004510 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04004511 }
4512
4513 /* if it's good, return it */
4514 if (!IS_ERR(tlink->tl_tcon))
4515 return tlink;
4516
4517 /* return error if we tried this already recently */
4518 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4519 cifs_put_tlink(tlink);
4520 return ERR_PTR(-EACCES);
4521 }
4522
4523 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4524 goto wait_for_construction;
4525 }
4526
4527 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4528 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4529 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4530
4531 if (IS_ERR(tlink->tl_tcon)) {
4532 cifs_put_tlink(tlink);
4533 return ERR_PTR(-EACCES);
4534 }
4535
4536 return tlink;
4537}
Jeff Layton2de970f2010-10-06 19:51:12 -04004538
4539/*
4540 * periodic workqueue job that scans tcon_tree for a superblock and closes
4541 * out tcons.
4542 */
4543static void
4544cifs_prune_tlinks(struct work_struct *work)
4545{
4546 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4547 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004548 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00004549 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04004550 struct rb_node *tmp;
4551 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004552
Jeff Laytonb647c352010-10-28 11:16:44 -04004553 /*
4554 * Because we drop the spinlock in the loop in order to put the tlink
4555 * it's not guarded against removal of links from the tree. The only
4556 * places that remove entries from the tree are this function and
4557 * umounts. Because this function is non-reentrant and is canceled
4558 * before umount can proceed, this is safe.
4559 */
4560 spin_lock(&cifs_sb->tlink_tree_lock);
4561 node = rb_first(root);
4562 while (node != NULL) {
4563 tmp = node;
4564 node = rb_next(tmp);
4565 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4566
4567 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4568 atomic_read(&tlink->tl_count) != 0 ||
4569 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4570 continue;
4571
4572 cifs_get_tlink(tlink);
4573 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4574 rb_erase(tmp, root);
4575
Jeff Layton2de970f2010-10-06 19:51:12 -04004576 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004577 cifs_put_tlink(tlink);
4578 spin_lock(&cifs_sb->tlink_tree_lock);
4579 }
4580 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004581
Jeff Laytonda472fc2012-03-23 14:40:53 -04004582 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004583 TLINK_IDLE_EXPIRE);
4584}