blob: 5df2c0698cda7a5ae093db0e3886b275bc0565cb [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070060extern mempool_t *cifs_req_poolp;
Steve Frenchf92a7202018-05-24 04:11:07 -050061extern bool disable_legacy_dialects;
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Jeff Layton2de970f2010-10-06 19:51:12 -040063/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040064#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040065#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040066
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040067enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040068 /* Mount options that take no arguments */
69 Opt_user_xattr, Opt_nouser_xattr,
70 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040071 Opt_forcegid, Opt_noforcegid,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040072 Opt_noblocksend, Opt_noautotune,
73 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
Steve French2baa2682014-09-27 02:19:01 -050074 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040075 Opt_mapchars, Opt_nomapchars, Opt_sfu,
76 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
Steve Frenchb3266142018-05-20 23:41:10 -050077 Opt_noposixpaths, Opt_nounix, Opt_unix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040078 Opt_nocase,
79 Opt_brl, Opt_nobrl,
Steve French3d4ef9a2018-04-25 22:19:09 -050080 Opt_handlecache, Opt_nohandlecache,
Steve French95932652016-09-23 01:36:34 -050081 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040082 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
83 Opt_nohard, Opt_nosoft,
84 Opt_nointr, Opt_intr,
85 Opt_nostrictsync, Opt_strictsync,
86 Opt_serverino, Opt_noserverino,
87 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
88 Opt_acl, Opt_noacl, Opt_locallease,
Jeff Layton1b359202012-09-19 15:20:27 -070089 Opt_sign, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040090 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -040091 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -050092 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -060093 Opt_resilient, Opt_noresilient,
Long Li8339dd32017-11-07 01:54:55 -070094 Opt_domainauto, Opt_rdma,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040095
96 /* Mount options which take numeric value */
97 Opt_backupuid, Opt_backupgid, Opt_uid,
98 Opt_cruid, Opt_gid, Opt_file_mode,
99 Opt_dirmode, Opt_port,
100 Opt_rsize, Opt_wsize, Opt_actimeo,
Steve French141891f2016-09-23 00:44:16 -0500101 Opt_echo_interval, Opt_max_credits,
Steve French8b217fe2016-11-11 22:36:20 -0600102 Opt_snapshot,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400103
104 /* Mount options which take string value */
105 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400106 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400107 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400108 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400109
110 /* Mount options to be ignored */
111 Opt_ignore,
112
113 /* Options which could be blank */
114 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100115 Opt_blank_user,
116 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400117
118 Opt_err
119};
120
121static const match_table_t cifs_mount_option_tokens = {
122
123 { Opt_user_xattr, "user_xattr" },
124 { Opt_nouser_xattr, "nouser_xattr" },
125 { Opt_forceuid, "forceuid" },
126 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400127 { Opt_forcegid, "forcegid" },
128 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400129 { Opt_noblocksend, "noblocksend" },
130 { Opt_noautotune, "noautotune" },
131 { Opt_hard, "hard" },
132 { Opt_soft, "soft" },
133 { Opt_perm, "perm" },
134 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500135 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400136 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500137 { Opt_mapposix, "mapposix" }, /* SFM style */
138 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400139 { Opt_sfu, "sfu" },
140 { Opt_nosfu, "nosfu" },
141 { Opt_nodfs, "nodfs" },
142 { Opt_posixpaths, "posixpaths" },
143 { Opt_noposixpaths, "noposixpaths" },
144 { Opt_nounix, "nounix" },
145 { Opt_nounix, "nolinux" },
Steve Frenchb3266142018-05-20 23:41:10 -0500146 { Opt_nounix, "noposix" },
147 { Opt_unix, "unix" },
148 { Opt_unix, "linux" },
149 { Opt_unix, "posix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400150 { Opt_nocase, "nocase" },
151 { Opt_nocase, "ignorecase" },
152 { Opt_brl, "brl" },
153 { Opt_nobrl, "nobrl" },
Steve French3d4ef9a2018-04-25 22:19:09 -0500154 { Opt_handlecache, "handlecache" },
155 { Opt_nohandlecache, "nohandlecache" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400156 { Opt_nobrl, "nolock" },
157 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400158 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400159 { Opt_setuids, "setuids" },
160 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500161 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400162 { Opt_dynperm, "dynperm" },
163 { Opt_nodynperm, "nodynperm" },
164 { Opt_nohard, "nohard" },
165 { Opt_nosoft, "nosoft" },
166 { Opt_nointr, "nointr" },
167 { Opt_intr, "intr" },
168 { Opt_nostrictsync, "nostrictsync" },
169 { Opt_strictsync, "strictsync" },
170 { Opt_serverino, "serverino" },
171 { Opt_noserverino, "noserverino" },
172 { Opt_rwpidforward, "rwpidforward" },
173 { Opt_cifsacl, "cifsacl" },
174 { Opt_nocifsacl, "nocifsacl" },
175 { Opt_acl, "acl" },
176 { Opt_noacl, "noacl" },
177 { Opt_locallease, "locallease" },
178 { Opt_sign, "sign" },
179 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400180 { Opt_noac, "noac" },
181 { Opt_fsc, "fsc" },
182 { Opt_mfsymlinks, "mfsymlinks" },
183 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400184 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400185 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500186 { Opt_persistent, "persistenthandles"},
187 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600188 { Opt_resilient, "resilienthandles"},
189 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530190 { Opt_domainauto, "domainauto"},
Long Li8339dd32017-11-07 01:54:55 -0700191 { Opt_rdma, "rdma"},
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400192
193 { Opt_backupuid, "backupuid=%s" },
194 { Opt_backupgid, "backupgid=%s" },
195 { Opt_uid, "uid=%s" },
196 { Opt_cruid, "cruid=%s" },
197 { Opt_gid, "gid=%s" },
198 { Opt_file_mode, "file_mode=%s" },
199 { Opt_dirmode, "dirmode=%s" },
200 { Opt_dirmode, "dir_mode=%s" },
201 { Opt_port, "port=%s" },
202 { Opt_rsize, "rsize=%s" },
203 { Opt_wsize, "wsize=%s" },
204 { Opt_actimeo, "actimeo=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600205 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500206 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600207 { Opt_snapshot, "snapshot=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400208
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100209 { Opt_blank_user, "user=" },
210 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400211 { Opt_user, "user=%s" },
212 { Opt_user, "username=%s" },
213 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100214 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400215 { Opt_pass, "pass=%s" },
216 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100217 { Opt_blank_ip, "ip=" },
218 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400219 { Opt_ip, "ip=%s" },
220 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400221 { Opt_ignore, "unc=%s" },
222 { Opt_ignore, "target=%s" },
223 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400224 { Opt_domain, "dom=%s" },
225 { Opt_domain, "domain=%s" },
226 { Opt_domain, "workgroup=%s" },
227 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400228 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400229 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400230 { Opt_netbiosname, "netbiosname=%s" },
231 { Opt_servern, "servern=%s" },
232 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400233 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400234 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400235 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400236
237 { Opt_ignore, "cred" },
238 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400239 { Opt_ignore, "cred=%s" },
240 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400241 { Opt_ignore, "guest" },
242 { Opt_ignore, "rw" },
243 { Opt_ignore, "ro" },
244 { Opt_ignore, "suid" },
245 { Opt_ignore, "nosuid" },
246 { Opt_ignore, "exec" },
247 { Opt_ignore, "noexec" },
248 { Opt_ignore, "nodev" },
249 { Opt_ignore, "noauto" },
250 { Opt_ignore, "dev" },
251 { Opt_ignore, "mand" },
252 { Opt_ignore, "nomand" },
253 { Opt_ignore, "_netdev" },
254
255 { Opt_err, NULL }
256};
257
258enum {
259 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
260 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400261 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
262 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400263 Opt_sec_none,
264
265 Opt_sec_err
266};
267
268static const match_table_t cifs_secflavor_tokens = {
269 { Opt_sec_krb5, "krb5" },
270 { Opt_sec_krb5i, "krb5i" },
271 { Opt_sec_krb5p, "krb5p" },
272 { Opt_sec_ntlmsspi, "ntlmsspi" },
273 { Opt_sec_ntlmssp, "ntlmssp" },
274 { Opt_ntlm, "ntlm" },
275 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400276 { Opt_sec_ntlmv2, "nontlm" },
277 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400278 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400279 { Opt_sec_lanman, "lanman" },
280 { Opt_sec_none, "none" },
281
282 { Opt_sec_err, NULL }
283};
284
Jeff Layton15b6a472012-05-16 07:50:15 -0400285/* cache flavors */
286enum {
287 Opt_cache_loose,
288 Opt_cache_strict,
289 Opt_cache_none,
290 Opt_cache_err
291};
292
293static const match_table_t cifs_cacheflavor_tokens = {
294 { Opt_cache_loose, "loose" },
295 { Opt_cache_strict, "strict" },
296 { Opt_cache_none, "none" },
297 { Opt_cache_err, NULL }
298};
299
Jeff Layton23db65f2012-05-15 12:20:51 -0400300static const match_table_t cifs_smb_version_tokens = {
301 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600302 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000303 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500304 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500305 { Smb_302, SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600306#ifdef CONFIG_CIFS_SMB311
307 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500308 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600309#endif /* SMB311 */
Steve French9764c022017-09-17 10:41:35 -0500310 { Smb_3any, SMB3ANY_VERSION_STRING },
311 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600312 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400313};
314
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300315static int ip_connect(struct TCP_Server_Info *server);
316static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400317static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400318static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400319static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -0500320 const char *devname, bool is_smb3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Jeff Laytond5c56052008-12-01 18:42:33 -0500322/*
323 * cifs tcp session reconnection
324 *
325 * mark tcp session as reconnecting so temporarily locked
326 * mark all smb sessions as reconnecting for tcp session
327 * reconnect tcp session
328 * wake up waiters on reconnection? - (not needed currently)
329 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400330int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331cifs_reconnect(struct TCP_Server_Info *server)
332{
333 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500334 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000335 struct cifs_ses *ses;
336 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000337 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400338 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000339
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000341 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000342 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 next time through the loop */
344 spin_unlock(&GlobalMid_Lock);
345 return rc;
346 } else
347 server->tcpStatus = CifsNeedReconnect;
348 spin_unlock(&GlobalMid_Lock);
349 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400350 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
Joe Perchesf96637b2013-05-04 22:12:25 -0500352 cifs_dbg(FYI, "Reconnecting tcp session\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 /* before reconnecting the tcp session, mark the smb session (uid)
355 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500356 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
357 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530358 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500359 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000360 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500361 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500362 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000363 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500364 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100366 if (ses->tcon_ipc)
367 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530369 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500370
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500372 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500373 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000374 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500375 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
376 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800377 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500378 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
379 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 sock_release(server->ssocket);
381 server->ssocket = NULL;
382 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500383 server->sequence_number = 0;
384 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500385 kfree(server->session_key.response);
386 server->session_key.response = NULL;
387 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000388 server->lstrp = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500390 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400391 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500392 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500394 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
395 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400396 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
397 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400398 list_move(&mid_entry->qhead, &retry_list);
399 }
400 spin_unlock(&GlobalMid_Lock);
Rabin Vincent820962d2015-12-23 07:32:41 +0100401 mutex_unlock(&server->srv_mutex);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400402
Joe Perchesf96637b2013-05-04 22:12:25 -0500403 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400404 list_for_each_safe(tmp, tmp2, &retry_list) {
405 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500406 list_del_init(&mid_entry->qhead);
407 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400410 do {
Steve French6c3d8902006-07-31 22:46:20 +0000411 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300412
413 /* we should try only the port we connected to before */
Jeff Layton73e216a2013-09-05 08:38:10 -0400414 mutex_lock(&server->srv_mutex);
Long Li781a8052017-11-22 17:38:36 -0700415 if (cifs_rdma_enabled(server))
416 rc = smbd_reconnect(server);
417 else
418 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000419 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500420 cifs_dbg(FYI, "reconnect error %d\n", rc);
Federico Sauter4afe2602015-03-17 17:45:28 +0100421 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700422 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 } else {
424 atomic_inc(&tcpSesReconnectCount);
425 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000426 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000427 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000428 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100429 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400431 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500432
Sachin Prabhub8c60012016-10-20 19:52:24 -0400433 if (server->tcpStatus == CifsNeedNegotiate)
434 mod_delayed_work(cifsiod_wq, &server->echo, 0);
435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 return rc;
437}
438
Jeff Laytonc74093b2011-01-11 07:24:23 -0500439static void
440cifs_echo_request(struct work_struct *work)
441{
442 int rc;
443 struct TCP_Server_Info *server = container_of(work,
444 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400445 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500446
Jeff Layton247ec9b2011-02-04 17:09:50 -0500447 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400448 * If we need to renegotiate, set echo interval to zero to
449 * immediately call echo service where we can renegotiate.
450 */
451 if (server->tcpStatus == CifsNeedNegotiate)
452 echo_interval = 0;
453 else
454 echo_interval = server->echo_interval;
455
456 /*
457 * We cannot send an echo if it is disabled.
458 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500459 */
Steve French4fcd1812016-06-22 20:12:05 -0500460
461 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400462 server->tcpStatus == CifsExiting ||
463 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400464 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600465 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500466 goto requeue_echo;
467
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400468 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500469 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500470 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
471 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500472
473requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400474 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500475}
476
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400477static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400478allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400479{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400480 if (!server->bigbuf) {
481 server->bigbuf = (char *)cifs_buf_get();
482 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500483 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400484 msleep(3000);
485 /* retry will check if exiting */
486 return false;
487 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400488 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400489 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400490 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400491 }
492
Jeff Layton2a37ef92011-10-19 15:29:23 -0400493 if (!server->smallbuf) {
494 server->smallbuf = (char *)cifs_small_buf_get();
495 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500496 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400497 msleep(1000);
498 /* retry will check if exiting */
499 return false;
500 }
501 /* beginning of smb buffer is cleared in our buf_get */
502 } else {
503 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400504 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400505 }
506
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400507 return true;
508}
509
Jeff Laytonba749e62011-10-11 06:41:32 -0400510static bool
511server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400512{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300513 /*
514 * We need to wait 2 echo intervals to make sure we handle such
515 * situations right:
516 * 1s client sends a normal SMB request
517 * 2s client gets a response
518 * 30s echo workqueue job pops, and decides we got a response recently
519 * and don't need to send another
520 * ...
521 * 65s kernel_recvmsg times out, and we see that we haven't gotten
522 * a response in >60s.
523 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200524 if ((server->tcpStatus == CifsGood ||
525 server->tcpStatus == CifsNeedNegotiate) &&
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600526 time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
527 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
528 server->hostname, (2 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400529 cifs_reconnect(server);
530 wake_up(&server->response_q);
531 return true;
532 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400533
Jeff Laytonba749e62011-10-11 06:41:32 -0400534 return false;
535}
536
Al Viro71335662016-01-09 19:54:50 -0500537static int
538cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400539{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400540 int length = 0;
541 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400542
Al Viro71335662016-01-09 19:54:50 -0500543 smb_msg->msg_control = NULL;
544 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400545
Al Viro71335662016-01-09 19:54:50 -0500546 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500547 try_to_freeze();
548
Al Viro71335662016-01-09 19:54:50 -0500549 if (server_unresponsive(server))
550 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700551 if (cifs_rdma_enabled(server) && server->smbd_conn)
552 length = smbd_recv(server->smbd_conn, smb_msg);
553 else
554 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500555
556 if (server->tcpStatus == CifsExiting)
557 return -ESHUTDOWN;
558
559 if (server->tcpStatus == CifsNeedReconnect) {
560 cifs_reconnect(server);
561 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400562 }
563
Al Viro71335662016-01-09 19:54:50 -0500564 if (length == -ERESTARTSYS ||
565 length == -EAGAIN ||
566 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400567 /*
568 * Minimum sleep to prevent looping, allowing socket
569 * to clear and app threads to set tcpStatus
570 * CifsNeedReconnect if server hung.
571 */
572 usleep_range(1000, 2000);
573 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400574 continue;
Al Viro71335662016-01-09 19:54:50 -0500575 }
576
577 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500578 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400579 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500580 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400581 }
582 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400583 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400584}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400585
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400586int
587cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
588 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400589{
Al Viro71335662016-01-09 19:54:50 -0500590 struct msghdr smb_msg;
591 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
592 iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400593
Al Viro71335662016-01-09 19:54:50 -0500594 return cifs_readv_from_socket(server, &smb_msg);
595}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400596
Al Viro71335662016-01-09 19:54:50 -0500597int
598cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700599 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500600{
601 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700602 struct bio_vec bv = {
603 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
Al Viro71335662016-01-09 19:54:50 -0500604 iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
605 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400606}
607
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400608static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400609is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400610{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400611 /*
612 * The first byte big endian of the length field,
613 * is actually not part of the length but the type
614 * with the most common, zero, as regular data.
615 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400616 switch (type) {
617 case RFC1002_SESSION_MESSAGE:
618 /* Regular SMB response */
619 return true;
620 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500621 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400622 break;
623 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500624 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400625 break;
626 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400627 /*
628 * We get this from Windows 98 instead of an error on
629 * SMB negprot response.
630 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500631 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400632 /* give server a second to clean up */
633 msleep(1000);
634 /*
635 * Always try 445 first on reconnect since we get NACK
636 * on some if we ever connected to port 139 (the NACK
637 * is since we do not begin with RFC1001 session
638 * initialize frame).
639 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400640 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400641 cifs_reconnect(server);
642 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400643 break;
644 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500645 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400646 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400647 }
648
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400649 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400650}
651
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400652void
653dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400654{
655#ifdef CONFIG_CIFS_STATS2
656 mid->when_received = jiffies;
657#endif
658 spin_lock(&GlobalMid_Lock);
659 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400660 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400661 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400662 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400663 list_del_init(&mid->qhead);
664 spin_unlock(&GlobalMid_Lock);
665}
666
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400667static void
668handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400669 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400670{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400671 if (server->ops->check_trans2 &&
672 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400673 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400674 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400675 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400676 /* Was previous buf put in mpx struct for multi-rsp? */
677 if (!mid->multiRsp) {
678 /* smb buffer will be freed by user thread */
679 if (server->large_buf)
680 server->bigbuf = NULL;
681 else
682 server->smallbuf = NULL;
683 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400684 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400685}
686
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400687static void clean_demultiplex_info(struct TCP_Server_Info *server)
688{
689 int length;
690
691 /* take it off the list, if it's not already */
692 spin_lock(&cifs_tcp_ses_lock);
693 list_del_init(&server->tcp_ses_list);
694 spin_unlock(&cifs_tcp_ses_lock);
695
696 spin_lock(&GlobalMid_Lock);
697 server->tcpStatus = CifsExiting;
698 spin_unlock(&GlobalMid_Lock);
699 wake_up_all(&server->response_q);
700
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400701 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300702 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400703 if (server->credits <= 0)
704 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300705 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400706 /*
707 * Although there should not be any requests blocked on this queue it
708 * can not hurt to be paranoid and try to wake up requests that may
709 * haven been blocked when more than 50 at time were on the wire to the
710 * same server - they now will see the session is in exit state and get
711 * out of SendReceive.
712 */
713 wake_up_all(&server->request_q);
714 /* give those requests time to exit */
715 msleep(125);
Long Libce9ce72017-11-22 17:38:38 -0700716 if (cifs_rdma_enabled(server) && server->smbd_conn) {
717 smbd_destroy(server->smbd_conn);
718 server->smbd_conn = NULL;
719 }
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400720 if (server->ssocket) {
721 sock_release(server->ssocket);
722 server->ssocket = NULL;
723 }
724
725 if (!list_empty(&server->pending_mid_q)) {
726 struct list_head dispose_list;
727 struct mid_q_entry *mid_entry;
728 struct list_head *tmp, *tmp2;
729
730 INIT_LIST_HEAD(&dispose_list);
731 spin_lock(&GlobalMid_Lock);
732 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
733 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500734 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400735 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400736 list_move(&mid_entry->qhead, &dispose_list);
737 }
738 spin_unlock(&GlobalMid_Lock);
739
740 /* now walk dispose list and issue callbacks */
741 list_for_each_safe(tmp, tmp2, &dispose_list) {
742 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500743 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400744 list_del_init(&mid_entry->qhead);
745 mid_entry->callback(mid_entry);
746 }
747 /* 1/8th of sec is more than enough time for them to exit */
748 msleep(125);
749 }
750
751 if (!list_empty(&server->pending_mid_q)) {
752 /*
753 * mpx threads have not exited yet give them at least the smb
754 * send timeout time for long ops.
755 *
756 * Due to delays on oplock break requests, we need to wait at
757 * least 45 seconds before giving up on a request getting a
758 * response and going ahead and killing cifsd.
759 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500760 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400761 msleep(46000);
762 /*
763 * If threads still have not exited they are probably never
764 * coming home not much else we can do but free the memory.
765 */
766 }
767
768 kfree(server->hostname);
769 kfree(server);
770
771 length = atomic_dec_return(&tcpSesAllocCount);
772 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700773 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400774}
775
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400776static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400777standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
778{
779 int length;
780 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +1000781 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400782
783 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100784 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
785 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500786 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400787 cifs_reconnect(server);
788 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400789 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400790 }
791
792 /* switch to large buffer if too big for a small one */
793 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
794 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400795 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400796 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400797 }
798
799 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400800 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100801 pdu_length - HEADER_SIZE(server) + 1
802 + server->vals->header_preamble_size);
803
Jeff Laytone9097ab2011-10-19 15:29:40 -0400804 if (length < 0)
805 return length;
806 server->total_read += length;
807
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400808 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400809
Pavel Shilovsky4326ed22016-11-17 15:24:46 -0800810 return cifs_handle_standard(server, mid);
811}
812
813int
814cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
815{
816 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
817 int length;
818
Jeff Laytone9097ab2011-10-19 15:29:40 -0400819 /*
820 * We know that we received enough to get to the MID as we
821 * checked the pdu_length earlier. Now check to see
822 * if the rest of the header is OK. We borrow the length
823 * var for the rest of the loop to avoid a new stack var.
824 *
825 * 48 bytes is enough to display the header and a little bit
826 * into the payload for debugging purposes.
827 */
Steve French373512e2015-12-18 13:05:30 -0600828 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400829 if (length != 0)
830 cifs_dump_mem("Bad SMB: ", buf,
831 min_t(unsigned int, server->total_read, 48));
832
Pavel Shilovsky511c54a2017-07-08 14:32:00 -0700833 if (server->ops->is_session_expired &&
834 server->ops->is_session_expired(buf)) {
835 cifs_reconnect(server);
836 wake_up(&server->response_q);
837 return -1;
838 }
839
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700840 if (server->ops->is_status_pending &&
841 server->ops->is_status_pending(buf, server, length))
842 return -1;
843
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500844 if (!mid)
845 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400846
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400847 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500848 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400849}
850
851static int
Al Viro7c97c202011-06-21 08:51:28 -0400852cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
854 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400855 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400856 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +1000857 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400858 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500859 struct task_struct *task_to_wake = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -0500863 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400864
865 length = atomic_inc_return(&tcpSesAllocCount);
866 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -0700867 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700869 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +0000870 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700871 if (try_to_freeze())
872 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700873
Jeff Layton2a37ef92011-10-19 15:29:23 -0400874 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400875 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700876
Jeff Layton2a37ef92011-10-19 15:29:23 -0400877 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400878 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000879 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000880
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400881 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400882 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +0000883 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +1000884
885 if (server->vals->header_preamble_size == 0)
886 server->total_read = 0;
887 else
888 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700889
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400890 /*
891 * The right amount was read from socket - 4 bytes,
892 * so we can now interpret the length field.
893 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400894 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -0700895
Joe Perchesf96637b2013-05-04 22:12:25 -0500896 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400897 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000898 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +1000899next_pdu:
900 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -0700901
Jeff Layton89482a52011-10-19 15:28:57 -0400902 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +1000903 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100904 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500905 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +1000906 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -0400907 cifs_reconnect(server);
908 wake_up(&server->response_q);
909 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700910 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400911
Jeff Layton89482a52011-10-19 15:28:57 -0400912 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100913 length = cifs_read_from_socket(server,
914 buf + server->vals->header_preamble_size,
915 HEADER_SIZE(server) - 1
916 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -0400917 if (length < 0)
918 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400919 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -0400920
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +1000921 if (server->ops->next_header) {
922 next_offset = server->ops->next_header(buf);
923 if (next_offset)
924 server->pdu_size = next_offset;
925 }
926
Lars Persson696e4202018-06-25 14:05:25 +0200927 mid_entry = NULL;
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -0800928 if (server->ops->is_transform_hdr &&
929 server->ops->receive_transform &&
930 server->ops->is_transform_hdr(buf)) {
931 length = server->ops->receive_transform(server,
932 &mid_entry);
933 } else {
934 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400935
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -0800936 if (!mid_entry || !mid_entry->receive)
937 length = standard_receive3(server, mid_entry);
938 else
939 length = mid_entry->receive(server, mid_entry);
940 }
Jeff Layton44d22d82011-10-19 15:29:49 -0400941
Lars Persson696e4202018-06-25 14:05:25 +0200942 if (length < 0) {
943 if (mid_entry)
944 cifs_mid_q_entry_release(mid_entry);
Steve Frenche4eb2952005-04-28 22:41:09 -0700945 continue;
Lars Persson696e4202018-06-25 14:05:25 +0200946 }
Steve Frenche4eb2952005-04-28 22:41:09 -0700947
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400948 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -0400949 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -0700950
Steve Frenchfda35942011-01-20 18:06:34 +0000951 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500952 if (mid_entry != NULL) {
Ronnie Sahlberge19b2bc2018-04-09 18:06:28 +1000953 mid_entry->resp_buf_size = server->pdu_size;
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800954 if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
955 mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
956 server->ops->handle_cancelled_mid)
957 server->ops->handle_cancelled_mid(
958 mid_entry->resp_buf,
959 server);
960
Jeff Layton2a37ef92011-10-19 15:29:23 -0400961 if (!mid_entry->multiRsp || mid_entry->multiEnd)
962 mid_entry->callback(mid_entry);
Lars Persson696e4202018-06-25 14:05:25 +0200963
964 cifs_mid_q_entry_release(mid_entry);
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800965 } else if (server->ops->is_oplock_break &&
966 server->ops->is_oplock_break(buf, server)) {
967 cifs_dbg(FYI, "Received oplock break\n");
968 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -0500969 cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
970 atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400971 cifs_dump_mem("Received Data is: ", buf,
972 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +0000973#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400974 if (server->ops->dump_detail)
Steve French71992e622018-05-06 15:58:51 -0500975 server->ops->dump_detail(buf, server);
Steve French39798772006-05-31 22:40:51 +0000976 cifs_dump_mids(server);
977#endif /* CIFS_DEBUG2 */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +1000978 }
979 if (pdu_length > server->pdu_size) {
980 if (!allocate_buffers(server))
981 continue;
982 pdu_length -= server->pdu_size;
983 server->total_read = 0;
984 server->large_buf = false;
985 buf = server->smallbuf;
986 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -0700987 }
988 } /* end while !EXITING */
989
Justin P. Mattockfd62cb72011-02-24 22:15:02 -0800990 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -0400991 cifs_buf_release(server->bigbuf);
992 if (server->smallbuf) /* no sense logging a debug message if NULL */
993 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500995 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400996 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500997
998 /* if server->tsk was NULL then wait for a signal before exiting */
999 if (!task_to_wake) {
1000 set_current_state(TASK_INTERRUPTIBLE);
1001 while (!signal_pending(current)) {
1002 schedule();
1003 set_current_state(TASK_INTERRUPTIBLE);
1004 }
1005 set_current_state(TASK_RUNNING);
1006 }
1007
Jeff Layton0468a2c2008-12-01 07:09:35 -05001008 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009}
1010
Jeff Laytonc359cf32007-11-16 22:22:06 +00001011/* extract the host portion of the UNC string */
1012static char *
1013extract_hostname(const char *unc)
1014{
1015 const char *src;
1016 char *dst, *delim;
1017 unsigned int len;
1018
1019 /* skip double chars at beginning of string */
1020 /* BB: check validity of these bytes? */
1021 src = unc + 2;
1022
1023 /* delimiter between hostname and sharename is always '\\' now */
1024 delim = strchr(src, '\\');
1025 if (!delim)
1026 return ERR_PTR(-EINVAL);
1027
1028 len = delim - src;
1029 dst = kmalloc((len + 1), GFP_KERNEL);
1030 if (dst == NULL)
1031 return ERR_PTR(-ENOMEM);
1032
1033 memcpy(dst, src, len);
1034 dst[len] = '\0';
1035
1036 return dst;
1037}
1038
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001039static int get_option_ul(substring_t args[], unsigned long *option)
1040{
1041 int rc;
1042 char *string;
1043
1044 string = match_strdup(args);
1045 if (string == NULL)
1046 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001047 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001048 kfree(string);
1049
1050 return rc;
1051}
1052
Eric W. Biederman3da46562013-02-06 01:37:39 -08001053static int get_option_uid(substring_t args[], kuid_t *result)
1054{
1055 unsigned long value;
1056 kuid_t uid;
1057 int rc;
1058
1059 rc = get_option_ul(args, &value);
1060 if (rc)
1061 return rc;
1062
1063 uid = make_kuid(current_user_ns(), value);
1064 if (!uid_valid(uid))
1065 return -EINVAL;
1066
1067 *result = uid;
1068 return 0;
1069}
1070
1071static int get_option_gid(substring_t args[], kgid_t *result)
1072{
1073 unsigned long value;
1074 kgid_t gid;
1075 int rc;
1076
1077 rc = get_option_ul(args, &value);
1078 if (rc)
1079 return rc;
1080
1081 gid = make_kgid(current_user_ns(), value);
1082 if (!gid_valid(gid))
1083 return -EINVAL;
1084
1085 *result = gid;
1086 return 0;
1087}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001088
1089static int cifs_parse_security_flavors(char *value,
1090 struct smb_vol *vol)
1091{
1092
1093 substring_t args[MAX_OPT_ARGS];
1094
Jeff Layton1e3cc572013-06-10 17:12:23 -05001095 /*
1096 * With mount options, the last one should win. Reset any existing
1097 * settings back to default.
1098 */
1099 vol->sectype = Unspecified;
1100 vol->sign = false;
1101
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001102 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001103 case Opt_sec_krb5p:
1104 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1105 return 1;
1106 case Opt_sec_krb5i:
1107 vol->sign = true;
1108 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001109 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001110 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001111 break;
1112 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001113 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001114 /* Fallthrough */
1115 case Opt_sec_ntlmssp:
1116 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001117 break;
1118 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001119 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001120 /* Fallthrough */
1121 case Opt_ntlm:
1122 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001123 break;
1124 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001125 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001126 /* Fallthrough */
1127 case Opt_sec_ntlmv2:
1128 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001129 break;
1130#ifdef CONFIG_CIFS_WEAK_PW_HASH
1131 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001132 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001133 break;
1134#endif
1135 case Opt_sec_none:
1136 vol->nullauth = 1;
1137 break;
1138 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001139 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001140 return 1;
1141 }
1142
1143 return 0;
1144}
1145
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001147cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1148{
1149 substring_t args[MAX_OPT_ARGS];
1150
1151 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1152 case Opt_cache_loose:
1153 vol->direct_io = false;
1154 vol->strict_io = false;
1155 break;
1156 case Opt_cache_strict:
1157 vol->direct_io = false;
1158 vol->strict_io = true;
1159 break;
1160 case Opt_cache_none:
1161 vol->direct_io = true;
1162 vol->strict_io = false;
1163 break;
1164 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001165 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001166 return 1;
1167 }
1168 return 0;
1169}
1170
1171static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001172cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001173{
1174 substring_t args[MAX_OPT_ARGS];
1175
1176 switch (match_token(value, cifs_smb_version_tokens, args)) {
1177 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001178 if (disable_legacy_dialects) {
1179 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1180 return 1;
1181 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001182 if (is_smb3) {
1183 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1184 return 1;
1185 }
Jeff Layton23db65f2012-05-15 12:20:51 -04001186 vol->ops = &smb1_operations;
1187 vol->vals = &smb1_values;
1188 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001189 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001190 if (disable_legacy_dialects) {
1191 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1192 return 1;
1193 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001194 if (is_smb3) {
1195 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1196 return 1;
1197 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001198 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001199 vol->vals = &smb20_values;
1200 break;
Steve French1080ef72011-02-24 18:07:19 +00001201 case Smb_21:
1202 vol->ops = &smb21_operations;
1203 vol->vals = &smb21_values;
1204 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001205 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001206 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001207 vol->vals = &smb30_values;
1208 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001209 case Smb_302:
1210 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1211 vol->vals = &smb302_values;
1212 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001213#ifdef CONFIG_CIFS_SMB311
1214 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001215 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001216 vol->vals = &smb311_values;
1217 break;
1218#endif /* SMB311 */
Steve French9764c022017-09-17 10:41:35 -05001219 case Smb_3any:
1220 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1221 vol->vals = &smb3any_values;
1222 break;
1223 case Smb_default:
1224 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1225 vol->vals = &smbdefault_values;
1226 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001227 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001228 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001229 return 1;
1230 }
1231 return 0;
1232}
1233
Jeff Laytond387a5c2012-12-10 06:10:46 -05001234/*
1235 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1236 * fields with the result. Returns 0 on success and an error otherwise.
1237 */
1238static int
1239cifs_parse_devname(const char *devname, struct smb_vol *vol)
1240{
1241 char *pos;
1242 const char *delims = "/\\";
1243 size_t len;
1244
1245 /* make sure we have a valid UNC double delimiter prefix */
1246 len = strspn(devname, delims);
1247 if (len != 2)
1248 return -EINVAL;
1249
1250 /* find delimiter between host and sharename */
1251 pos = strpbrk(devname + 2, delims);
1252 if (!pos)
1253 return -EINVAL;
1254
1255 /* skip past delimiter */
1256 ++pos;
1257
1258 /* now go until next delimiter or end of string */
1259 len = strcspn(pos, delims);
1260
1261 /* move "pos" up to delimiter or NULL */
1262 pos += len;
1263 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1264 if (!vol->UNC)
1265 return -ENOMEM;
1266
1267 convert_delimiter(vol->UNC, '\\');
1268
Sachin Prabhu11e31642016-02-08 13:44:01 +05301269 /* skip any delimiter */
1270 if (*pos == '/' || *pos == '\\')
1271 pos++;
1272
1273 /* If pos is NULL then no prepath */
1274 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001275 return 0;
1276
1277 vol->prepath = kstrdup(pos, GFP_KERNEL);
1278 if (!vol->prepath)
1279 return -ENOMEM;
1280
1281 return 0;
1282}
1283
Jeff Layton23db65f2012-05-15 12:20:51 -04001284static int
Sean Finneyb9468452011-04-11 13:19:32 +00001285cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001286 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001288 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001289 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 unsigned int temp_len, i, j;
1291 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001292 short int override_uid = -1;
1293 short int override_gid = -1;
1294 bool uid_specified = false;
1295 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001296 bool sloppy = false;
1297 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001298 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001299 char *string = NULL;
1300 char *tmp_end, *value;
1301 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001302 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001303 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001304 unsigned short port = 0;
1305 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
1307 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001308 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001309 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Jeff Layton6ee95422012-11-26 11:09:57 -05001311 /* ensure we always start with zeroed-out smb_vol */
1312 memset(vol, 0, sizeof(*vol));
1313
Jeff Layton88463992010-11-22 15:31:03 -05001314 /*
1315 * does not have to be perfect mapping since field is
1316 * informational, only used for servers that do not support
1317 * port 445 and it can be overridden at mount time
1318 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001319 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1320 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001321 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1322
Jeff Layton1397f2e2011-01-07 11:30:28 -05001323 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001324 /* null target name indicates to use *SMBSERVR default called name
1325 if we end up sending RFC1001 session initialize */
1326 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001327 vol->cred_uid = current_uid();
1328 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001329 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001330
Steve French2baa2682014-09-27 02:19:01 -05001331 /*
1332 * default to SFM style remapping of seven reserved characters
1333 * unless user overrides it or we negotiate CIFS POSIX where
1334 * it is unnecessary. Can not simultaneously use more than one mapping
1335 * since then readdir could list files that open could not open
1336 */
1337 vol->remap = true;
1338
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001339 /* default to only allowing write access to owner of the mount */
1340 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
1342 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001343 /* default is always to request posix paths. */
1344 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001345 /* default to using server inode numbers where available */
1346 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001347
Jeff Layton1b359202012-09-19 15:20:27 -07001348 /* default is to use strict cifs caching semantics */
1349 vol->strict_io = true;
1350
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301351 vol->actimeo = CIFS_DEF_ACTIMEO;
1352
Steve French9764c022017-09-17 10:41:35 -05001353 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1354 vol->ops = &smb30_operations;
1355 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001356
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001357 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1358
Sean Finneyb9468452011-04-11 13:19:32 +00001359 if (!mountdata)
1360 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Sean Finneyb9468452011-04-11 13:19:32 +00001362 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1363 if (!mountdata_copy)
1364 goto cifs_parse_mount_err;
1365
1366 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001367 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001368
Steve French50c2f752007-07-13 00:33:32 +00001369 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001370 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 separator[0] = options[4];
1372 options += 5;
1373 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001374 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 }
1376 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001377 vol->backupuid_specified = false; /* no backup intent for a user */
1378 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001379
Jeff Layton37d4f992013-05-24 07:40:05 -04001380 switch (cifs_parse_devname(devname, vol)) {
1381 case 0:
1382 break;
1383 case -ENOMEM:
1384 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1385 goto cifs_parse_mount_err;
1386 case -EINVAL:
1387 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1388 goto cifs_parse_mount_err;
1389 default:
1390 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1391 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001392 }
1393
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001395 substring_t args[MAX_OPT_ARGS];
1396 unsigned long option;
1397 int token;
1398
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 if (!*data)
1400 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001402 token = match_token(data, cifs_mount_option_tokens, args);
1403
1404 switch (token) {
1405
1406 /* Ingnore the following */
1407 case Opt_ignore:
1408 break;
1409
1410 /* Boolean values */
1411 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001413 break;
1414 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001416 break;
1417 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001418 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001419 break;
1420 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001421 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001422 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001423 case Opt_forcegid:
1424 override_gid = 1;
1425 break;
1426 case Opt_noforcegid:
1427 override_gid = 0;
1428 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001429 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001430 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001431 break;
1432 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001433 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001434 break;
1435 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001437 break;
1438 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001440 break;
1441 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001443 break;
1444 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001446 break;
1447 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001448 vol->sfu_remap = true;
1449 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001450 break;
1451 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001452 vol->sfu_remap = false;
1453 break;
1454 case Opt_mapposix:
1455 vol->remap = true;
1456 vol->sfu_remap = false; /* disable SFU mapping */
1457 break;
1458 case Opt_nomapposix:
1459 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 break;
1461 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001462 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001463 break;
1464 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001465 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001466 break;
1467 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001468 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001469 break;
1470 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001471 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001472 break;
1473 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001474 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001475 break;
1476 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001477 if (vol->linux_ext)
1478 cifs_dbg(VFS,
1479 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001480 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001481 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001482 case Opt_unix:
1483 if (vol->no_linux_ext)
1484 cifs_dbg(VFS,
1485 "conflicting unix mount options\n");
1486 vol->linux_ext = 1;
1487 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001488 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001489 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001490 break;
1491 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001492 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001493 break;
1494 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001495 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001496 /*
1497 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001498 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001499 * local vfs will do advisory
1500 */
Steve French50c2f752007-07-13 00:33:32 +00001501 if (vol->file_mode ==
1502 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001503 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001504 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001505 case Opt_nohandlecache:
1506 vol->nohandlecache = 1;
1507 break;
1508 case Opt_handlecache:
1509 vol->nohandlecache = 0;
1510 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001511 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001512 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001513 break;
1514 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001516 break;
1517 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001519 break;
Steve French95932652016-09-23 01:36:34 -05001520 case Opt_setuidfromacl:
1521 vol->setuidfromacl = 1;
1522 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001523 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001524 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001525 break;
1526 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001527 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001528 break;
1529 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001531 break;
1532 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001534 break;
1535 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001537 break;
1538 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001540 break;
1541 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001542 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001543 break;
1544 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001545 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001546 break;
1547 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001549 break;
1550 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001552 break;
1553 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001554 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001555 break;
1556 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001557 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001558 break;
1559 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001560 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001561 break;
1562 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001564 break;
1565 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001567 break;
1568 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001569 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001570 break;
1571 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001572 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001573 break;
1574 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001575 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001576 * is a per tree connection (mount) not a per socket
1577 * or per-smb connection option in the protocol
1578 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1579 */
Steve French95b1cb92008-05-15 16:44:38 +00001580 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001581 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001582 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001583 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001584 break;
1585 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301586#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001587 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001588 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301589#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301590 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001591 break;
1592 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001593 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001594 break;
1595 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001596 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001597 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001598 case Opt_sloppy:
1599 sloppy = true;
1600 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001601 case Opt_nosharesock:
1602 vol->nosharesock = true;
1603 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001604 case Opt_nopersistent:
1605 vol->nopersistent = true;
1606 if (vol->persistent) {
1607 cifs_dbg(VFS,
1608 "persistenthandles mount options conflict\n");
1609 goto cifs_parse_mount_err;
1610 }
1611 break;
1612 case Opt_persistent:
1613 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001614 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001615 cifs_dbg(VFS,
1616 "persistenthandles mount options conflict\n");
1617 goto cifs_parse_mount_err;
1618 }
1619 break;
Steve French592fafe2015-11-03 10:08:53 -06001620 case Opt_resilient:
1621 vol->resilient = true;
1622 if (vol->persistent) {
1623 cifs_dbg(VFS,
1624 "persistenthandles mount options conflict\n");
1625 goto cifs_parse_mount_err;
1626 }
1627 break;
1628 case Opt_noresilient:
1629 vol->resilient = false; /* already the default */
1630 break;
Germano Percossi39566442016-12-15 12:31:18 +05301631 case Opt_domainauto:
1632 vol->domainauto = true;
1633 break;
Long Li8339dd32017-11-07 01:54:55 -07001634 case Opt_rdma:
1635 vol->rdma = true;
1636 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001637
1638 /* Numeric Values */
1639 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001640 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001641 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1642 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001643 goto cifs_parse_mount_err;
1644 }
1645 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001646 break;
1647 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001648 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001649 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1650 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001651 goto cifs_parse_mount_err;
1652 }
1653 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001654 break;
1655 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001656 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001657 cifs_dbg(VFS, "%s: Invalid uid value\n",
1658 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001659 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001661 uid_specified = true;
1662 break;
1663 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001664 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001665 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1666 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001667 goto cifs_parse_mount_err;
1668 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001669 break;
1670 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001671 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001672 cifs_dbg(VFS, "%s: Invalid gid value\n",
1673 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001674 goto cifs_parse_mount_err;
1675 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001676 gid_specified = true;
1677 break;
1678 case Opt_file_mode:
1679 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001680 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1681 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001682 goto cifs_parse_mount_err;
1683 }
1684 vol->file_mode = option;
1685 break;
1686 case Opt_dirmode:
1687 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001688 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1689 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001690 goto cifs_parse_mount_err;
1691 }
1692 vol->dir_mode = option;
1693 break;
1694 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001695 if (get_option_ul(args, &option) ||
1696 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001697 cifs_dbg(VFS, "%s: Invalid port value\n",
1698 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001699 goto cifs_parse_mount_err;
1700 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001701 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001702 break;
1703 case Opt_rsize:
1704 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001705 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1706 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001707 goto cifs_parse_mount_err;
1708 }
1709 vol->rsize = option;
1710 break;
1711 case Opt_wsize:
1712 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001713 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1714 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001715 goto cifs_parse_mount_err;
1716 }
1717 vol->wsize = option;
1718 break;
1719 case Opt_actimeo:
1720 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001721 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1722 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001723 goto cifs_parse_mount_err;
1724 }
1725 vol->actimeo = HZ * option;
1726 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001727 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001728 goto cifs_parse_mount_err;
1729 }
1730 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06001731 case Opt_echo_interval:
1732 if (get_option_ul(args, &option)) {
1733 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
1734 __func__);
1735 goto cifs_parse_mount_err;
1736 }
1737 vol->echo_interval = option;
1738 break;
Steve French8b217fe2016-11-11 22:36:20 -06001739 case Opt_snapshot:
1740 if (get_option_ul(args, &option)) {
1741 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
1742 __func__);
1743 goto cifs_parse_mount_err;
1744 }
1745 vol->snapshot_time = option;
1746 break;
Steve French141891f2016-09-23 00:44:16 -05001747 case Opt_max_credits:
1748 if (get_option_ul(args, &option) || (option < 20) ||
1749 (option > 60000)) {
1750 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1751 __func__);
1752 goto cifs_parse_mount_err;
1753 }
1754 vol->max_credits = option;
1755 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001756
1757 /* String Arguments */
1758
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001759 case Opt_blank_user:
1760 /* null user, ie. anonymous authentication */
1761 vol->nullauth = 1;
1762 vol->username = NULL;
1763 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001764 case Opt_user:
1765 string = match_strdup(args);
1766 if (string == NULL)
1767 goto out_nomem;
1768
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001769 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1770 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001771 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001772 goto cifs_parse_mount_err;
1773 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001774
1775 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001776 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001777 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001778 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001779 break;
1780 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001781 /* passwords have to be handled differently
1782 * to allow the character used for deliminator
1783 * to be passed within them
1784 */
1785
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001786 /*
1787 * Check if this is a case where the password
1788 * starts with a delimiter
1789 */
1790 tmp_end = strchr(data, '=');
1791 tmp_end++;
1792 if (!(tmp_end < end && tmp_end[1] == delim)) {
1793 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01001794 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001795 vol->password = NULL;
1796 break;
1797 }
1798 /* Yes it is. Drop down to Opt_pass below.*/
1799 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001800 /* Obtain the value string */
1801 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001802 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803
1804 /* Set tmp_end to end of the string */
1805 tmp_end = (char *) value + strlen(value);
1806
1807 /* Check if following character is the deliminator
1808 * If yes, we have encountered a double deliminator
1809 * reset the NULL character to the deliminator
1810 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301811 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001812 tmp_end[0] = delim;
1813
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301814 /* Keep iterating until we get to a single
1815 * deliminator OR the end
1816 */
1817 while ((tmp_end = strchr(tmp_end, delim))
1818 != NULL && (tmp_end[1] == delim)) {
1819 tmp_end = (char *) &tmp_end[2];
1820 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001821
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301822 /* Reset var options to point to next element */
1823 if (tmp_end) {
1824 tmp_end[0] = '\0';
1825 options = (char *) &tmp_end[1];
1826 } else
1827 /* Reached the end of the mount option
1828 * string */
1829 options = end;
1830 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001831
Aurelien Aptel97f4b722018-01-25 15:59:39 +01001832 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001833 /* Now build new password string */
1834 temp_len = strlen(value);
1835 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1836 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001837 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001838 goto cifs_parse_mount_err;
1839 }
1840
1841 for (i = 0, j = 0; i < temp_len; i++, j++) {
1842 vol->password[j] = value[i];
1843 if ((value[i] == delim) &&
1844 value[i+1] == delim)
1845 /* skip the second deliminator */
1846 i++;
1847 }
1848 vol->password[j] = '\0';
1849 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001850 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001851 /* FIXME: should this be an error instead? */
1852 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001853 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001854 case Opt_ip:
1855 string = match_strdup(args);
1856 if (string == NULL)
1857 goto out_nomem;
1858
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001859 if (!cifs_convert_address(dstaddr, string,
1860 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001861 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001862 goto cifs_parse_mount_err;
1863 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001864 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001865 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001866 case Opt_domain:
1867 string = match_strdup(args);
1868 if (string == NULL)
1869 goto out_nomem;
1870
Chen Gang057d6332013-07-19 09:01:36 +08001871 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
1872 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001873 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001874 goto cifs_parse_mount_err;
1875 }
1876
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001877 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001878 vol->domainname = kstrdup(string, GFP_KERNEL);
1879 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001880 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001881 goto cifs_parse_mount_err;
1882 }
Joe Perchesf96637b2013-05-04 22:12:25 -05001883 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001884 break;
1885 case Opt_srcaddr:
1886 string = match_strdup(args);
1887 if (string == NULL)
1888 goto out_nomem;
1889
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001890 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001891 (struct sockaddr *)&vol->srcaddr,
1892 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001893 pr_warn("CIFS: Could not parse srcaddr: %s\n",
1894 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001895 goto cifs_parse_mount_err;
1896 }
1897 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001898 case Opt_iocharset:
1899 string = match_strdup(args);
1900 if (string == NULL)
1901 goto out_nomem;
1902
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001903 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001904 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001905 goto cifs_parse_mount_err;
1906 }
1907
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001908 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001909 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001910 vol->iocharset = kstrdup(string,
1911 GFP_KERNEL);
1912 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001913 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001914 goto cifs_parse_mount_err;
1915 }
1916 }
1917 /* if iocharset not set then load_nls_default
1918 * is used by caller
1919 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001920 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001921 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001922 case Opt_netbiosname:
1923 string = match_strdup(args);
1924 if (string == NULL)
1925 goto out_nomem;
1926
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001927 memset(vol->source_rfc1001_name, 0x20,
1928 RFC1001_NAME_LEN);
1929 /*
1930 * FIXME: are there cases in which a comma can
1931 * be valid in workstation netbios name (and
1932 * need special handling)?
1933 */
1934 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1935 /* don't ucase netbiosname for user */
1936 if (string[i] == 0)
1937 break;
1938 vol->source_rfc1001_name[i] = string[i];
1939 }
1940 /* The string has 16th byte zero still from
1941 * set at top of the function
1942 */
1943 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001944 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001945 break;
1946 case Opt_servern:
1947 /* servernetbiosname specified override *SMBSERVER */
1948 string = match_strdup(args);
1949 if (string == NULL)
1950 goto out_nomem;
1951
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001952 /* last byte, type, is 0x20 for servr type */
1953 memset(vol->target_rfc1001_name, 0x20,
1954 RFC1001_NAME_LEN_WITH_NULL);
1955
1956 /* BB are there cases in which a comma can be
1957 valid in this workstation netbios name
1958 (and need special handling)? */
1959
1960 /* user or mount helper must uppercase the
1961 netbios name */
1962 for (i = 0; i < 15; i++) {
1963 if (string[i] == 0)
1964 break;
1965 vol->target_rfc1001_name[i] = string[i];
1966 }
1967 /* The string has 16th byte zero still from
1968 set at top of the function */
1969 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001970 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001971 break;
1972 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05001973 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001974 string = match_strdup(args);
1975 if (string == NULL)
1976 goto out_nomem;
1977
Steve French7e682f72017-08-31 21:34:24 -05001978 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001979 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05001980 if (strlen(string) > 1) {
1981 pr_warn("Bad mount helper ver=%s. Did "
1982 "you want SMB1 (CIFS) dialect "
1983 "and mean to type vers=1.0 "
1984 "instead?\n", string);
1985 goto cifs_parse_mount_err;
1986 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001987 /* This is the default */
1988 break;
1989 }
1990 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05001991 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001992 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001993 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05001994 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04001995 string = match_strdup(args);
1996 if (string == NULL)
1997 goto out_nomem;
1998
Steve Frenchc7c137b2018-06-06 17:59:29 -05001999 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002000 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002001 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002002 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002003 case Opt_sec:
2004 string = match_strdup(args);
2005 if (string == NULL)
2006 goto out_nomem;
2007
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002008 if (cifs_parse_security_flavors(string, vol) != 0)
2009 goto cifs_parse_mount_err;
2010 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002011 case Opt_cache:
2012 string = match_strdup(args);
2013 if (string == NULL)
2014 goto out_nomem;
2015
2016 if (cifs_parse_cache_flavor(string, vol) != 0)
2017 goto cifs_parse_mount_err;
2018 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002019 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002020 /*
2021 * An option we don't recognize. Save it off for later
2022 * if we haven't already found one
2023 */
2024 if (!invalid)
2025 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002026 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002028 /* Free up any allocated string */
2029 kfree(string);
2030 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002032
Jeff Laytond8162552012-03-23 14:40:56 -04002033 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002034 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002035 goto cifs_parse_mount_err;
2036 }
2037
Long Li8339dd32017-11-07 01:54:55 -07002038 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2039 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2040 goto cifs_parse_mount_err;
2041 }
2042
Jeff Layton8a8798a2012-01-17 16:09:15 -05002043#ifndef CONFIG_KEYS
2044 /* Muliuser mounts require CONFIG_KEYS support */
2045 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002046 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002047 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002048 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002049#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002050 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002051 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002052 goto cifs_parse_mount_err;
2053 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002054
Jeff Layton62a1a432012-12-10 06:10:45 -05002055 /* make sure UNC has a share name */
2056 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002057 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002058 goto cifs_parse_mount_err;
2059 }
2060
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002061 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002062 int len;
2063 const char *slash;
2064
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002065 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002066 /* Use the address part of the UNC. */
2067 slash = strchr(&vol->UNC[2], '\\');
2068 len = slash - &vol->UNC[2];
2069 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002070 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002071 goto cifs_parse_mount_err;
2072 }
2073 }
2074
2075 /* set the port that we got earlier */
2076 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002078 if (uid_specified)
2079 vol->override_uid = override_uid;
2080 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002081 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002082
2083 if (gid_specified)
2084 vol->override_gid = override_gid;
2085 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002086 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002087
Steve French7e682f72017-08-31 21:34:24 -05002088 if (got_version == false)
2089 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002090 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002091 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002092 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2093 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002094
Sean Finneyb9468452011-04-11 13:19:32 +00002095 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002097
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002098out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002099 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002100cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002101 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002102 kfree(mountdata_copy);
2103 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104}
2105
Ben Greear3eb9a882010-09-01 17:06:02 -07002106/** Returns true if srcaddr isn't specified and rhs isn't
2107 * specified, or if srcaddr is specified and
2108 * matches the IP address of the rhs argument.
2109 */
Jeff Layton45151482010-07-06 20:43:02 -04002110static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002111srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2112{
2113 switch (srcaddr->sa_family) {
2114 case AF_UNSPEC:
2115 return (rhs->sa_family == AF_UNSPEC);
2116 case AF_INET: {
2117 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2118 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2119 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2120 }
2121 case AF_INET6: {
2122 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002123 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002124 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2125 }
2126 default:
2127 WARN_ON(1);
2128 return false; /* don't expect to be here */
2129 }
2130}
2131
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002132/*
2133 * If no port is specified in addr structure, we try to match with 445 port
2134 * and if it fails - with 139 ports. It should be called only if address
2135 * families of server and addr are equal.
2136 */
2137static bool
2138match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2139{
Steve French6da97912011-03-13 18:55:55 +00002140 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002141
2142 switch (addr->sa_family) {
2143 case AF_INET:
2144 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2145 port = ((struct sockaddr_in *) addr)->sin_port;
2146 break;
2147 case AF_INET6:
2148 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2149 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2150 break;
2151 default:
2152 WARN_ON(1);
2153 return false;
2154 }
2155
2156 if (!port) {
2157 port = htons(CIFS_PORT);
2158 if (port == *sport)
2159 return true;
2160
2161 port = htons(RFC1001_PORT);
2162 }
2163
2164 return port == *sport;
2165}
Ben Greear3eb9a882010-09-01 17:06:02 -07002166
2167static bool
2168match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2169 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170{
Jeff Layton45151482010-07-06 20:43:02 -04002171 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002172 case AF_INET: {
2173 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2174 struct sockaddr_in *srv_addr4 =
2175 (struct sockaddr_in *)&server->dstaddr;
2176
2177 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002178 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002179 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002180 }
2181 case AF_INET6: {
2182 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2183 struct sockaddr_in6 *srv_addr6 =
2184 (struct sockaddr_in6 *)&server->dstaddr;
2185
Jeff Layton45151482010-07-06 20:43:02 -04002186 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002187 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002188 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002189 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002190 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002191 break;
2192 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002193 default:
2194 WARN_ON(1);
2195 return false; /* don't expect to be here */
2196 }
Jeff Layton45151482010-07-06 20:43:02 -04002197
Ben Greear3eb9a882010-09-01 17:06:02 -07002198 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2199 return false;
2200
Jeff Layton45151482010-07-06 20:43:02 -04002201 return true;
2202}
2203
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002204static bool
2205match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2206{
Jeff Layton3f618222013-06-12 19:52:14 -05002207 /*
2208 * The select_sectype function should either return the vol->sectype
2209 * that was specified, or "Unspecified" if that sectype was not
2210 * compatible with the given NEGOTIATE request.
2211 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302212 if (server->ops->select_sectype(server, vol->sectype)
2213 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002214 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002215
Jeff Layton3f618222013-06-12 19:52:14 -05002216 /*
2217 * Now check if signing mode is acceptable. No need to check
2218 * global_secflags at this point since if MUST_SIGN is set then
2219 * the server->sign had better be too.
2220 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002221 if (vol->sign && !server->sign)
2222 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002223
2224 return true;
2225}
2226
Jeff Layton9fa114f2012-11-26 11:09:57 -05002227static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002228{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002229 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2230
Jeff Laytona0b3df52013-05-24 07:40:59 -04002231 if (vol->nosharesock)
2232 return 0;
2233
Steve French9764c022017-09-17 10:41:35 -05002234 /* BB update this for smb3any and default case */
Jeff Layton23db65f2012-05-15 12:20:51 -04002235 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2236 return 0;
2237
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002238 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2239 return 0;
2240
2241 if (!match_address(server, addr,
2242 (struct sockaddr *)&vol->srcaddr))
2243 return 0;
2244
2245 if (!match_port(server, addr))
2246 return 0;
2247
2248 if (!match_security(server, vol))
2249 return 0;
2250
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002251 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002252 return 0;
2253
Long Li8339dd32017-11-07 01:54:55 -07002254 if (server->rdma != vol->rdma)
2255 return 0;
2256
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002257 return 1;
2258}
2259
Jeff Layton45151482010-07-06 20:43:02 -04002260static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002261cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002262{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002263 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302265 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002266 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002267 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002268 continue;
2269
Jeff Laytone7ddee92008-11-14 13:44:38 -05002270 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302271 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002272 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002273 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302275 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 return NULL;
2277}
2278
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002279void
2280cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002282 struct task_struct *task;
2283
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302284 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002285 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302286 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002287 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002289
Rob Landleyf1d0c992011-01-22 15:44:05 -06002290 put_net(cifs_net_ns(server));
2291
Jeff Laytone7ddee92008-11-14 13:44:38 -05002292 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302293 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002294
Jeff Laytonc74093b2011-01-11 07:24:23 -05002295 cancel_delayed_work_sync(&server->echo);
2296
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002297 if (from_reconnect)
2298 /*
2299 * Avoid deadlock here: reconnect work calls
2300 * cifs_put_tcp_session() at its end. Need to be sure
2301 * that reconnect work does nothing with server pointer after
2302 * that step.
2303 */
2304 cancel_delayed_work(&server->reconnect);
2305 else
2306 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002307
Jeff Laytone7ddee92008-11-14 13:44:38 -05002308 spin_lock(&GlobalMid_Lock);
2309 server->tcpStatus = CifsExiting;
2310 spin_unlock(&GlobalMid_Lock);
2311
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002312 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302313 cifs_fscache_release_client_cookie(server);
2314
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002315 kfree(server->session_key.response);
2316 server->session_key.response = NULL;
2317 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002318
2319 task = xchg(&server->tsk, NULL);
2320 if (task)
2321 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322}
2323
Jeff Layton63c038c2008-12-01 18:41:46 -05002324static struct TCP_Server_Info *
2325cifs_get_tcp_session(struct smb_vol *volume_info)
2326{
2327 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002328 int rc;
2329
Joe Perchesf96637b2013-05-04 22:12:25 -05002330 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002331
2332 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002333 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002334 if (tcp_ses)
2335 return tcp_ses;
2336
2337 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2338 if (!tcp_ses) {
2339 rc = -ENOMEM;
2340 goto out_err;
2341 }
2342
Jeff Layton23db65f2012-05-15 12:20:51 -04002343 tcp_ses->ops = volume_info->ops;
2344 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002345 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002346 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2347 if (IS_ERR(tcp_ses->hostname)) {
2348 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002349 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002350 }
2351
2352 tcp_ses->noblocksnd = volume_info->noblocksnd;
2353 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002354 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002355 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002356 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002357 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002358 init_waitqueue_head(&tcp_ses->response_q);
2359 init_waitqueue_head(&tcp_ses->request_q);
2360 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2361 mutex_init(&tcp_ses->srv_mutex);
2362 memcpy(tcp_ses->workstation_RFC1001_name,
2363 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2364 memcpy(tcp_ses->server_RFC1001_name,
2365 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002366 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002367 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002368 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002369 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002370 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2371 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002372 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002373 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2374 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002375 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2376 sizeof(tcp_ses->srcaddr));
2377 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2378 sizeof(tcp_ses->dstaddr));
Steve Frenchfa70b872016-09-22 00:39:34 -05002379 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002380 /*
2381 * at this point we are the only ones with the pointer
2382 * to the struct since the kernel thread not created yet
2383 * no need to spinlock this init of tcpStatus or srv_count
2384 */
2385 tcp_ses->tcpStatus = CifsNew;
2386 ++tcp_ses->srv_count;
2387
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002388 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2389 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2390 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2391 else
2392 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002393 if (tcp_ses->rdma) {
2394#ifndef CONFIG_CIFS_SMB_DIRECT
2395 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2396 rc = -ENOENT;
2397 goto out_err_crypto_release;
2398#endif
2399 tcp_ses->smbd_conn = smbd_get_connection(
2400 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2401 if (tcp_ses->smbd_conn) {
2402 cifs_dbg(VFS, "RDMA transport established\n");
2403 rc = 0;
2404 goto smbd_connected;
2405 } else {
2406 rc = -ENOENT;
2407 goto out_err_crypto_release;
2408 }
2409 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002410 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002411 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002412 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002413 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002414 }
Long Li2f894642017-11-22 17:38:34 -07002415smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002416 /*
2417 * since we're in a cifs function already, we know that
2418 * this will succeed. No need for try_module_get().
2419 */
2420 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002421 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002422 tcp_ses, "cifsd");
2423 if (IS_ERR(tcp_ses->tsk)) {
2424 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002425 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002426 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002427 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002428 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002429 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002430
2431 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302432 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002433 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302434 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002435
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302436 cifs_fscache_get_client_cookie(tcp_ses);
2437
Jeff Laytonc74093b2011-01-11 07:24:23 -05002438 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002439 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002440
Jeff Layton63c038c2008-12-01 18:41:46 -05002441 return tcp_ses;
2442
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002443out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002444 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002445
Rob Landleyf1d0c992011-01-22 15:44:05 -06002446 put_net(cifs_net_ns(tcp_ses));
2447
Jeff Layton63c038c2008-12-01 18:41:46 -05002448out_err:
2449 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002450 if (!IS_ERR(tcp_ses->hostname))
2451 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002452 if (tcp_ses->ssocket)
2453 sock_release(tcp_ses->ssocket);
2454 kfree(tcp_ses);
2455 }
2456 return ERR_PTR(rc);
2457}
2458
Steve French96daf2b2011-05-27 04:34:02 +00002459static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002460{
Jeff Layton3f618222013-06-12 19:52:14 -05002461 if (vol->sectype != Unspecified &&
2462 vol->sectype != ses->sectype)
2463 return 0;
2464
2465 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002466 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002467 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002468 return 0;
2469 break;
2470 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002471 /* NULL username means anonymous session */
2472 if (ses->user_name == NULL) {
2473 if (!vol->nullauth)
2474 return 0;
2475 break;
2476 }
2477
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002478 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002479 if (strncmp(ses->user_name,
2480 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002481 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002482 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002483 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002484 ses->password != NULL &&
2485 strncmp(ses->password,
2486 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002487 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002488 return 0;
2489 }
2490 return 1;
2491}
2492
Aurelien Aptelb327a712018-01-24 13:46:10 +01002493/**
2494 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2495 *
2496 * A new IPC connection is made and stored in the session
2497 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2498 */
2499static int
2500cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2501{
2502 int rc = 0, xid;
2503 struct cifs_tcon *tcon;
2504 struct nls_table *nls_codepage;
2505 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2506 bool seal = false;
2507
2508 /*
2509 * If the mount request that resulted in the creation of the
2510 * session requires encryption, force IPC to be encrypted too.
2511 */
2512 if (volume_info->seal) {
2513 if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
2514 seal = true;
2515 else {
2516 cifs_dbg(VFS,
2517 "IPC: server doesn't support encryption\n");
2518 return -EOPNOTSUPP;
2519 }
2520 }
2521
2522 tcon = tconInfoAlloc();
2523 if (tcon == NULL)
2524 return -ENOMEM;
2525
2526 snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->serverName);
2527
2528 /* cannot fail */
2529 nls_codepage = load_nls_default();
2530
2531 xid = get_xid();
2532 tcon->ses = ses;
2533 tcon->ipc = true;
2534 tcon->seal = seal;
2535 rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
2536 free_xid(xid);
2537
2538 if (rc) {
2539 cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
2540 tconInfoFree(tcon);
2541 goto out;
2542 }
2543
2544 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2545
2546 ses->tcon_ipc = tcon;
2547out:
2548 unload_nls(nls_codepage);
2549 return rc;
2550}
2551
2552/**
2553 * cifs_free_ipc - helper to release the session IPC tcon
2554 *
2555 * Needs to be called everytime a session is destroyed
2556 */
2557static int
2558cifs_free_ipc(struct cifs_ses *ses)
2559{
2560 int rc = 0, xid;
2561 struct cifs_tcon *tcon = ses->tcon_ipc;
2562
2563 if (tcon == NULL)
2564 return 0;
2565
2566 if (ses->server->ops->tree_disconnect) {
2567 xid = get_xid();
2568 rc = ses->server->ops->tree_disconnect(xid, tcon);
2569 free_xid(xid);
2570 }
2571
2572 if (rc)
2573 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
2574
2575 tconInfoFree(tcon);
2576 ses->tcon_ipc = NULL;
2577 return rc;
2578}
2579
Steve French96daf2b2011-05-27 04:34:02 +00002580static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002581cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582{
Steve French96daf2b2011-05-27 04:34:02 +00002583 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302585 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002586 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002587 if (ses->status == CifsExiting)
2588 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002589 if (!match_session(ses, vol))
2590 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002591 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302592 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002593 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302595 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 return NULL;
2597}
2598
Jeff Layton14fbf502008-11-14 13:53:46 -05002599static void
Steve French96daf2b2011-05-27 04:34:02 +00002600cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002601{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002602 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002603 struct TCP_Server_Info *server = ses->server;
2604
Joe Perchesf96637b2013-05-04 22:12:25 -05002605 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002606
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302607 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002608 if (ses->status == CifsExiting) {
2609 spin_unlock(&cifs_tcp_ses_lock);
2610 return;
2611 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002612 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302613 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002614 return;
2615 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002616 if (ses->status == CifsGood)
2617 ses->status = CifsExiting;
2618 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002619
Aurelien Aptelb327a712018-01-24 13:46:10 +01002620 cifs_free_ipc(ses);
2621
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002622 if (ses->status == CifsExiting && server->ops->logoff) {
2623 xid = get_xid();
2624 rc = server->ops->logoff(xid, ses);
2625 if (rc)
2626 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2627 __func__, rc);
2628 _free_xid(xid);
2629 }
2630
2631 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002632 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302633 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002634
Jeff Layton14fbf502008-11-14 13:53:46 -05002635 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002636 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05002637}
2638
Jeff Layton8a8798a2012-01-17 16:09:15 -05002639#ifdef CONFIG_KEYS
2640
Chen Gang057d6332013-07-19 09:01:36 +08002641/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2642#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002643
2644/* Populate username and pw fields from keyring if possible */
2645static int
2646cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2647{
2648 int rc = 0;
David Howells146aa8b2015-10-21 14:04:48 +01002649 const char *delim, *payload;
2650 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002651 ssize_t len;
2652 struct key *key;
2653 struct TCP_Server_Info *server = ses->server;
2654 struct sockaddr_in *sa;
2655 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01002656 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002657
2658 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2659 if (!desc)
2660 return -ENOMEM;
2661
2662 /* try to find an address key first */
2663 switch (server->dstaddr.ss_family) {
2664 case AF_INET:
2665 sa = (struct sockaddr_in *)&server->dstaddr;
2666 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2667 break;
2668 case AF_INET6:
2669 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2670 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2671 break;
2672 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002673 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2674 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002675 rc = -EINVAL;
2676 goto out_err;
2677 }
2678
Joe Perchesf96637b2013-05-04 22:12:25 -05002679 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002680 key = request_key(&key_type_logon, desc, "");
2681 if (IS_ERR(key)) {
2682 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002683 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002684 rc = PTR_ERR(key);
2685 goto out_err;
2686 }
2687
2688 /* didn't work, try to find a domain key */
2689 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002690 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002691 key = request_key(&key_type_logon, desc, "");
2692 if (IS_ERR(key)) {
2693 rc = PTR_ERR(key);
2694 goto out_err;
2695 }
2696 }
2697
2698 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00002699 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002700 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002701 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002702 goto out_key_put;
2703 }
2704
2705 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01002706 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002707 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002708 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002709 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002710 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2711 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002712 rc = -EINVAL;
2713 goto out_key_put;
2714 }
2715
2716 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002717 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002718 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2719 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002720 rc = -EINVAL;
2721 goto out_key_put;
2722 }
2723
2724 vol->username = kstrndup(payload, len, GFP_KERNEL);
2725 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002726 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2727 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002728 rc = -ENOMEM;
2729 goto out_key_put;
2730 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002731 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002732
2733 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002734 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002735 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002736 rc = -EINVAL;
2737 kfree(vol->username);
2738 vol->username = NULL;
2739 goto out_key_put;
2740 }
2741
2742 ++delim;
2743 vol->password = kstrndup(delim, len, GFP_KERNEL);
2744 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002745 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2746 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002747 rc = -ENOMEM;
2748 kfree(vol->username);
2749 vol->username = NULL;
2750 goto out_key_put;
2751 }
2752
2753out_key_put:
2754 up_read(&key->sem);
2755 key_put(key);
2756out_err:
2757 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002758 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002759 return rc;
2760}
2761#else /* ! CONFIG_KEYS */
2762static inline int
2763cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2764 struct cifs_ses *ses __attribute__((unused)))
2765{
2766 return -ENOSYS;
2767}
2768#endif /* CONFIG_KEYS */
2769
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002770/**
2771 * cifs_get_smb_ses - get a session matching @volume_info data from @server
2772 *
2773 * This function assumes it is being called from cifs_mount() where we
2774 * already got a server reference (server refcount +1). See
2775 * cifs_get_tcon() for refcount explanations.
2776 */
Steve French96daf2b2011-05-27 04:34:02 +00002777static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002778cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2779{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002780 int rc = -ENOMEM;
2781 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002782 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002783 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2784 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002785
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002786 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002787
Jeff Layton4ff67b72010-07-06 20:43:02 -04002788 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002789 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002790 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2791 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002792
Jeff Layton36988c72010-04-24 07:57:43 -04002793 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002794 rc = cifs_negotiate_protocol(xid, ses);
2795 if (rc) {
2796 mutex_unlock(&ses->session_mutex);
2797 /* problem -- put our ses reference */
2798 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002799 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002800 return ERR_PTR(rc);
2801 }
Jeff Layton36988c72010-04-24 07:57:43 -04002802 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002803 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002804 rc = cifs_setup_session(xid, ses,
2805 volume_info->local_nls);
2806 if (rc) {
2807 mutex_unlock(&ses->session_mutex);
2808 /* problem -- put our reference */
2809 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002810 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002811 return ERR_PTR(rc);
2812 }
2813 }
2814 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002815
2816 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002817 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002818 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002819 return ses;
2820 }
2821
Joe Perchesf96637b2013-05-04 22:12:25 -05002822 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002823 ses = sesInfoAlloc();
2824 if (ses == NULL)
2825 goto get_ses_fail;
2826
2827 /* new SMB session uses our server ref */
2828 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002829 if (server->dstaddr.ss_family == AF_INET6)
2830 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002831 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002832 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002833
Steve French8727c8a2011-02-25 01:11:56 -06002834 if (volume_info->username) {
2835 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2836 if (!ses->user_name)
2837 goto get_ses_fail;
2838 }
Jeff Layton36988c72010-04-24 07:57:43 -04002839
2840 /* volume_info->password freed at unmount */
2841 if (volume_info->password) {
2842 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2843 if (!ses->password)
2844 goto get_ses_fail;
2845 }
2846 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002847 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2848 if (!ses->domainName)
2849 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002850 }
Germano Percossi39566442016-12-15 12:31:18 +05302851 if (volume_info->domainauto)
2852 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002853 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002854 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002855
Jeff Layton28e11bd2013-05-26 07:01:00 -04002856 ses->sectype = volume_info->sectype;
2857 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04002858
2859 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002860 rc = cifs_negotiate_protocol(xid, ses);
2861 if (!rc)
2862 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002863 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002864 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002865 goto get_ses_fail;
2866
2867 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302868 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002869 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302870 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002871
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002872 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002873
2874 cifs_setup_ipc(ses, volume_info);
2875
Jeff Layton36988c72010-04-24 07:57:43 -04002876 return ses;
2877
2878get_ses_fail:
2879 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002880 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002881 return ERR_PTR(rc);
2882}
2883
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002884static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002885{
2886 if (tcon->tidStatus == CifsExiting)
2887 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002888 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002889 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002890 if (tcon->seal != volume_info->seal)
2891 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002892 if (tcon->snapshot_time != volume_info->snapshot_time)
2893 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002894 return 1;
2895}
2896
Steve French96daf2b2011-05-27 04:34:02 +00002897static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06002898cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899{
2900 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002901 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302903 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002904 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002905 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002906 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002907 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002908 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302909 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910 return tcon;
2911 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302912 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913 return NULL;
2914}
2915
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002916void
Steve French96daf2b2011-05-27 04:34:02 +00002917cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002918{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002919 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01002920 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002921
Aurelien Aptelb327a712018-01-24 13:46:10 +01002922 /*
2923 * IPC tcon share the lifetime of their session and are
2924 * destroyed in the session put function
2925 */
2926 if (tcon == NULL || tcon->ipc)
2927 return;
2928
2929 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05002930 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302931 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002932 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302933 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002934 return;
2935 }
2936
2937 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302938 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002939
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002940 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002941 if (ses->server->ops->tree_disconnect)
2942 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002943 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002944
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302945 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002946 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002947 cifs_put_smb_ses(ses);
2948}
2949
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002950/**
2951 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
2952 *
2953 * - tcon refcount is the number of mount points using the tcon.
2954 * - ses refcount is the number of tcon using the session.
2955 *
2956 * 1. This function assumes it is being called from cifs_mount() where
2957 * we already got a session reference (ses refcount +1).
2958 *
2959 * 2. Since we're in the context of adding a mount point, the end
2960 * result should be either:
2961 *
2962 * a) a new tcon already allocated with refcount=1 (1 mount point) and
2963 * its session refcount incremented (1 new tcon). This +1 was
2964 * already done in (1).
2965 *
2966 * b) an existing tcon with refcount+1 (add a mount point to it) and
2967 * identical ses refcount (no new tcon). Because of (1) we need to
2968 * decrement the ses refcount.
2969 */
Steve French96daf2b2011-05-27 04:34:02 +00002970static struct cifs_tcon *
2971cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002972{
2973 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002974 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002975
Steve French8b217fe2016-11-11 22:36:20 -06002976 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002977 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002978 /*
2979 * tcon has refcount already incremented but we need to
2980 * decrement extra ses reference gotten by caller (case b)
2981 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002982 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002983 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002984 return tcon;
2985 }
2986
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002987 if (!ses->server->ops->tree_connect) {
2988 rc = -ENOSYS;
2989 goto out_fail;
2990 }
2991
Jeff Laytond00c28d2010-04-24 07:57:44 -04002992 tcon = tconInfoAlloc();
2993 if (tcon == NULL) {
2994 rc = -ENOMEM;
2995 goto out_fail;
2996 }
2997
Steve French8b217fe2016-11-11 22:36:20 -06002998 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06002999 if (ses->server->vals->protocol_id == 0) {
3000 cifs_dbg(VFS,
3001 "Use SMB2 or later for snapshot mount option\n");
3002 rc = -EOPNOTSUPP;
3003 goto out_fail;
3004 } else
3005 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003006 }
3007
Jeff Laytond00c28d2010-04-24 07:57:44 -04003008 tcon->ses = ses;
3009 if (volume_info->password) {
3010 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3011 if (!tcon->password) {
3012 rc = -ENOMEM;
3013 goto out_fail;
3014 }
3015 }
3016
Steve French23657ad2018-04-22 15:14:58 -05003017 if (volume_info->seal) {
3018 if (ses->server->vals->protocol_id == 0) {
3019 cifs_dbg(VFS,
3020 "SMB3 or later required for encryption\n");
3021 rc = -EOPNOTSUPP;
3022 goto out_fail;
3023 } else if (tcon->ses->server->capabilities &
3024 SMB2_GLOBAL_CAP_ENCRYPTION)
3025 tcon->seal = true;
3026 else {
3027 cifs_dbg(VFS, "Encryption is not supported on share\n");
3028 rc = -EOPNOTSUPP;
3029 goto out_fail;
3030 }
3031 }
3032
Steve Frenchb3266142018-05-20 23:41:10 -05003033#ifdef CONFIG_CIFS_SMB311
3034 if ((volume_info->linux_ext) && (ses->server->posix_ext_supported)) {
Steve French2fbb5642018-06-12 12:11:31 -05003035 if (ses->server->vals->protocol_id == SMB311_PROT_ID) {
Steve Frenchb3266142018-05-20 23:41:10 -05003036 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003037 printk_once(KERN_WARNING
3038 "SMB3.11 POSIX Extensions are experimental\n");
3039 }
Steve Frenchb3266142018-05-20 23:41:10 -05003040 }
3041#endif /* 311 */
3042
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003043 /*
3044 * BB Do we need to wrap session_mutex around this TCon call and Unix
3045 * SetFS as we do on SessSetup and reconnect?
3046 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003047 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003048 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3049 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003050 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003051 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003052 if (rc)
3053 goto out_fail;
3054
3055 if (volume_info->nodfs) {
3056 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05003057 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003058 }
Steve Frenchb618f002015-11-03 09:15:03 -06003059 tcon->use_persistent = false;
3060 /* check if SMB2 or later, CIFS does not support persistent handles */
3061 if (volume_info->persistent) {
3062 if (ses->server->vals->protocol_id == 0) {
3063 cifs_dbg(VFS,
3064 "SMB3 or later required for persistent handles\n");
3065 rc = -EOPNOTSUPP;
3066 goto out_fail;
3067 } else if (ses->server->capabilities &
3068 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3069 tcon->use_persistent = true;
3070 else /* persistent handles requested but not supported */ {
3071 cifs_dbg(VFS,
3072 "Persistent handles not supported on share\n");
3073 rc = -EOPNOTSUPP;
3074 goto out_fail;
3075 }
3076 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3077 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3078 && (volume_info->nopersistent == false)) {
3079 cifs_dbg(FYI, "enabling persistent handles\n");
3080 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003081 } else if (volume_info->resilient) {
3082 if (ses->server->vals->protocol_id == 0) {
3083 cifs_dbg(VFS,
3084 "SMB2.1 or later required for resilient handles\n");
3085 rc = -EOPNOTSUPP;
3086 goto out_fail;
3087 }
3088 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003089 }
3090
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003091 /*
3092 * We can have only one retry value for a connection to a share so for
3093 * resources mounted more than once to the same server share the last
3094 * value passed in for the retry flag is used.
3095 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003096 tcon->retry = volume_info->retry;
3097 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003098 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003099 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003100 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003101
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303102 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003103 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303104 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003105
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303106 cifs_fscache_get_super_cookie(tcon);
3107
Jeff Laytond00c28d2010-04-24 07:57:44 -04003108 return tcon;
3109
3110out_fail:
3111 tconInfoFree(tcon);
3112 return ERR_PTR(rc);
3113}
3114
Jeff Layton9d002df2010-10-06 19:51:11 -04003115void
3116cifs_put_tlink(struct tcon_link *tlink)
3117{
3118 if (!tlink || IS_ERR(tlink))
3119 return;
3120
3121 if (!atomic_dec_and_test(&tlink->tl_count) ||
3122 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3123 tlink->tl_time = jiffies;
3124 return;
3125 }
3126
3127 if (!IS_ERR(tlink_tcon(tlink)))
3128 cifs_put_tcon(tlink_tcon(tlink));
3129 kfree(tlink);
3130 return;
3131}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003132
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003133static int
3134compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3135{
3136 struct cifs_sb_info *old = CIFS_SB(sb);
3137 struct cifs_sb_info *new = mnt_data->cifs_sb;
3138
3139 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3140 return 0;
3141
3142 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
3143 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
3144 return 0;
3145
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003146 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003147 * We want to share sb only if we don't specify an r/wsize or
3148 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003149 */
3150 if (new->wsize && new->wsize < old->wsize)
3151 return 0;
3152
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003153 if (new->rsize && new->rsize < old->rsize)
3154 return 0;
3155
Eric W. Biederman1f682332013-02-06 01:20:20 -08003156 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003157 return 0;
3158
3159 if (old->mnt_file_mode != new->mnt_file_mode ||
3160 old->mnt_dir_mode != new->mnt_dir_mode)
3161 return 0;
3162
3163 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3164 return 0;
3165
3166 if (old->actimeo != new->actimeo)
3167 return 0;
3168
3169 return 1;
3170}
3171
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003172static int
3173match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3174{
3175 struct cifs_sb_info *old = CIFS_SB(sb);
3176 struct cifs_sb_info *new = mnt_data->cifs_sb;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003177 bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3178 bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003179
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003180 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003181 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003182 else if (!old_set && !new_set)
3183 return 1;
3184
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003185 return 0;
3186}
3187
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003188int
3189cifs_match_super(struct super_block *sb, void *data)
3190{
3191 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3192 struct smb_vol *volume_info;
3193 struct cifs_sb_info *cifs_sb;
3194 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003195 struct cifs_ses *ses;
3196 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003197 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003198 int rc = 0;
3199
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003200 spin_lock(&cifs_tcp_ses_lock);
3201 cifs_sb = CIFS_SB(sb);
3202 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3203 if (IS_ERR(tlink)) {
3204 spin_unlock(&cifs_tcp_ses_lock);
3205 return rc;
3206 }
3207 tcon = tlink_tcon(tlink);
3208 ses = tcon->ses;
3209 tcp_srv = ses->server;
3210
3211 volume_info = mnt_data->vol;
3212
Jeff Layton9fa114f2012-11-26 11:09:57 -05003213 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003214 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003215 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003216 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003217 rc = 0;
3218 goto out;
3219 }
3220
3221 rc = compare_mount_options(sb, mnt_data);
3222out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003223 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003224 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003225 return rc;
3226}
3227
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003229get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003230 const struct nls_table *nls_codepage, unsigned int *num_referrals,
3231 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233 int rc = 0;
3234
Aurelien Aptelb327a712018-01-24 13:46:10 +01003235 if (!ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003236 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003238 *num_referrals = 0;
3239 *referrals = NULL;
3240
Aurelien Aptelb327a712018-01-24 13:46:10 +01003241 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
3242 referrals, num_referrals,
3243 nls_codepage, remap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 return rc;
3245}
3246
Jeff Layton09e50d52008-07-23 10:11:19 -04003247#ifdef CONFIG_DEBUG_LOCK_ALLOC
3248static struct lock_class_key cifs_key[2];
3249static struct lock_class_key cifs_slock_key[2];
3250
3251static inline void
3252cifs_reclassify_socket4(struct socket *sock)
3253{
3254 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003255 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003256 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3257 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3258}
3259
3260static inline void
3261cifs_reclassify_socket6(struct socket *sock)
3262{
3263 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003264 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003265 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3266 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3267}
3268#else
3269static inline void
3270cifs_reclassify_socket4(struct socket *sock)
3271{
3272}
3273
3274static inline void
3275cifs_reclassify_socket6(struct socket *sock)
3276{
3277}
3278#endif
3279
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003281static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282{
Steve French50c2f752007-07-13 00:33:32 +00003283 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284
Steve French50c2f752007-07-13 00:33:32 +00003285 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286 /* mask a nibble at a time and encode */
3287 target[j] = 'A' + (0x0F & (source[i] >> 4));
3288 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003289 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003290 }
3291
3292}
3293
Ben Greear3eb9a882010-09-01 17:06:02 -07003294static int
3295bind_socket(struct TCP_Server_Info *server)
3296{
3297 int rc = 0;
3298 if (server->srcaddr.ss_family != AF_UNSPEC) {
3299 /* Bind to the specified local IP address */
3300 struct socket *socket = server->ssocket;
3301 rc = socket->ops->bind(socket,
3302 (struct sockaddr *) &server->srcaddr,
3303 sizeof(server->srcaddr));
3304 if (rc < 0) {
3305 struct sockaddr_in *saddr4;
3306 struct sockaddr_in6 *saddr6;
3307 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3308 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3309 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05003310 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3311 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003312 else
Joe Perchesf96637b2013-05-04 22:12:25 -05003313 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3314 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003315 }
3316 }
3317 return rc;
3318}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319
3320static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003321ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322{
3323 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003324 /*
3325 * some servers require RFC1001 sessinit before sending
3326 * negprot - BB check reconnection in case where second
3327 * sessinit is sent but no second negprot
3328 */
3329 struct rfc1002_session_packet *ses_init_buf;
3330 struct smb_hdr *smb_buf;
3331 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3332 GFP_KERNEL);
3333 if (ses_init_buf) {
3334 ses_init_buf->trailer.session_req.called_len = 32;
3335
Colin Ian King997152f2016-01-25 16:25:54 +00003336 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003337 rfc1002mangle(ses_init_buf->trailer.
3338 session_req.called_name,
3339 server->server_RFC1001_name,
3340 RFC1001_NAME_LEN_WITH_NULL);
3341 else
3342 rfc1002mangle(ses_init_buf->trailer.
3343 session_req.called_name,
3344 DEFAULT_CIFS_CALLED_NAME,
3345 RFC1001_NAME_LEN_WITH_NULL);
3346
3347 ses_init_buf->trailer.session_req.calling_len = 32;
3348
3349 /*
3350 * calling name ends in null (byte 16) from old smb
3351 * convention.
3352 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003353 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003354 rfc1002mangle(ses_init_buf->trailer.
3355 session_req.calling_name,
3356 server->workstation_RFC1001_name,
3357 RFC1001_NAME_LEN_WITH_NULL);
3358 else
3359 rfc1002mangle(ses_init_buf->trailer.
3360 session_req.calling_name,
3361 "LINUX_CIFS_CLNT",
3362 RFC1001_NAME_LEN_WITH_NULL);
3363
3364 ses_init_buf->trailer.session_req.scope1 = 0;
3365 ses_init_buf->trailer.session_req.scope2 = 0;
3366 smb_buf = (struct smb_hdr *)ses_init_buf;
3367
3368 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003369 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003370 rc = smb_send(server, smb_buf, 0x44);
3371 kfree(ses_init_buf);
3372 /*
3373 * RFC1001 layer in at least one server
3374 * requires very short break before negprot
3375 * presumably because not expecting negprot
3376 * to follow so fast. This is a simple
3377 * solution that works without
3378 * complicating the code and causes no
3379 * significant slowing down on mount
3380 * for everyone else
3381 */
3382 usleep_range(1000, 2000);
3383 }
3384 /*
3385 * else the negprot may still work without this
3386 * even though malloc failed
3387 */
3388
3389 return rc;
3390}
3391
3392static int
3393generic_ip_connect(struct TCP_Server_Info *server)
3394{
3395 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003396 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003397 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003398 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003399 struct sockaddr *saddr;
3400
3401 saddr = (struct sockaddr *) &server->dstaddr;
3402
3403 if (server->dstaddr.ss_family == AF_INET6) {
3404 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3405 slen = sizeof(struct sockaddr_in6);
3406 sfamily = AF_INET6;
3407 } else {
3408 sport = ((struct sockaddr_in *) saddr)->sin_port;
3409 slen = sizeof(struct sockaddr_in);
3410 sfamily = AF_INET;
3411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003413 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003414 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3415 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003417 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003418 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003421
3422 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003423 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003424 server->ssocket = socket;
3425 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003426 if (sfamily == AF_INET6)
3427 cifs_reclassify_socket6(socket);
3428 else
3429 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 }
3431
Ben Greear3eb9a882010-09-01 17:06:02 -07003432 rc = bind_socket(server);
3433 if (rc < 0)
3434 return rc;
3435
Jeff Laytond5c56052008-12-01 18:42:33 -05003436 /*
3437 * Eventually check for other socket options to change from
3438 * the default. sock_setsockopt not used because it expects
3439 * user space buffer
3440 */
3441 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003442 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003443
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003444 /* make the bufsizes depend on wsize/rsize and max requests */
3445 if (server->noautotune) {
3446 if (socket->sk->sk_sndbuf < (200 * 1024))
3447 socket->sk->sk_sndbuf = 200 * 1024;
3448 if (socket->sk->sk_rcvbuf < (140 * 1024))
3449 socket->sk->sk_rcvbuf = 140 * 1024;
3450 }
3451
Steve French6a5fa2362010-01-01 01:28:43 +00003452 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003453 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003454 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3455 (char *)&val, sizeof(val));
3456 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003457 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3458 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003459 }
3460
Joe Perchesf96637b2013-05-04 22:12:25 -05003461 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003462 socket->sk->sk_sndbuf,
3463 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3464
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003465 rc = socket->ops->connect(socket, saddr, slen, 0);
3466 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003467 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003468 sock_release(socket);
3469 server->ssocket = NULL;
3470 return rc;
3471 }
3472
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003473 if (sport == htons(RFC1001_PORT))
3474 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003475
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 return rc;
3477}
3478
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003479static int
3480ip_connect(struct TCP_Server_Info *server)
3481{
Steve French6da97912011-03-13 18:55:55 +00003482 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003483 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3484 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3485
3486 if (server->dstaddr.ss_family == AF_INET6)
3487 sport = &addr6->sin6_port;
3488 else
3489 sport = &addr->sin_port;
3490
3491 if (*sport == 0) {
3492 int rc;
3493
3494 /* try with 445 port at first */
3495 *sport = htons(CIFS_PORT);
3496
3497 rc = generic_ip_connect(server);
3498 if (rc >= 0)
3499 return rc;
3500
3501 /* if it failed, try with 139 port */
3502 *sport = htons(RFC1001_PORT);
3503 }
3504
3505 return generic_ip_connect(server);
3506}
3507
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003508void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003509 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003510{
3511 /* if we are reconnecting then should we check to see if
3512 * any requested capabilities changed locally e.g. via
3513 * remount but we can not do much about it here
3514 * if they have (even if we could detect it by the following)
3515 * Perhaps we could add a backpointer to array of sb from tcon
3516 * or if we change to make all sb to same share the same
3517 * sb as NFS - then we only have one backpointer to sb.
3518 * What if we wanted to mount the server share twice once with
3519 * and once without posixacls or posix paths? */
3520 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003521
Steve Frenchc18c8422007-07-18 23:21:09 +00003522 if (vol_info && vol_info->no_linux_ext) {
3523 tcon->fsUnixInfo.Capability = 0;
3524 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003525 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003526 return;
3527 } else if (vol_info)
3528 tcon->unix_ext = 1; /* Unix Extensions supported */
3529
3530 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003531 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003532 return;
3533 }
Steve French50c2f752007-07-13 00:33:32 +00003534
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003535 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003536 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003537 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003538 /* check for reconnect case in which we do not
3539 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003540 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003541 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003542 originally at mount time */
3543 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3544 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003545 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3546 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003547 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003548 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003549 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003550 cifs_dbg(VFS, "possible reconnect error\n");
3551 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003552 }
Steve French8af18972007-02-14 04:42:51 +00003553 }
Steve French50c2f752007-07-13 00:33:32 +00003554
Steve French6848b732011-05-26 18:38:54 +00003555 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003556 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003557
Steve French8af18972007-02-14 04:42:51 +00003558 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003559 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003560 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003561 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003562 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003563 if (cifs_sb)
3564 cifs_sb->mnt_cifs_flags |=
3565 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003566 }
3567
Steve French75865f8c2007-06-24 18:30:48 +00003568 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003569 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003570 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003571 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003572 if (cifs_sb)
3573 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003574 CIFS_MOUNT_POSIX_PATHS;
3575 }
Steve French50c2f752007-07-13 00:33:32 +00003576
Joe Perchesf96637b2013-05-04 22:12:25 -05003577 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003578#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003579 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003580 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003581 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003582 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003583 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003584 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003585 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003586 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003587 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003588 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003589 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003590 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003591 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003592 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003593 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003594 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003595 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003596 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003597#endif /* CIFS_DEBUG2 */
3598 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003599 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003600 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003601 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003602 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 +00003603
Steve French8af18972007-02-14 04:42:51 +00003604 }
3605 }
3606}
3607
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003608int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003609 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003610{
Jeff Layton2de970f2010-10-06 19:51:12 -04003611 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3612
Al Viro2ced6f62011-06-17 09:20:04 -04003613 spin_lock_init(&cifs_sb->tlink_tree_lock);
3614 cifs_sb->tlink_tree = RB_ROOT;
3615
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003616 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003617 * Temporarily set r/wsize for matching superblock. If we end up using
3618 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003619 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003620 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003621 cifs_sb->wsize = pvolume_info->wsize;
3622
Steve French3b795212008-11-13 19:45:32 +00003623 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3624 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3625 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3626 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003627 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3628 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003629
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303630 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003631 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303632
Steve French3b795212008-11-13 19:45:32 +00003633 if (pvolume_info->noperm)
3634 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3635 if (pvolume_info->setuids)
3636 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05003637 if (pvolume_info->setuidfromacl)
3638 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00003639 if (pvolume_info->server_ino)
3640 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3641 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003642 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3643 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003644 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3645 if (pvolume_info->no_xattr)
3646 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3647 if (pvolume_info->sfu_emul)
3648 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3649 if (pvolume_info->nobrl)
3650 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05003651 if (pvolume_info->nohandlecache)
3652 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00003653 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003654 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003655 if (pvolume_info->mand_lock)
3656 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003657 if (pvolume_info->rwpidforward)
3658 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003659 if (pvolume_info->cifs_acl)
3660 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003661 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003662 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003663 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3664 }
3665 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003666 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003667 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3668 }
Steve French3b795212008-11-13 19:45:32 +00003669 if (pvolume_info->override_uid)
3670 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3671 if (pvolume_info->override_gid)
3672 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3673 if (pvolume_info->dynperm)
3674 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303675 if (pvolume_info->fsc)
3676 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003677 if (pvolume_info->multiuser)
3678 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3679 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003680 if (pvolume_info->strict_io)
3681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003682 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003683 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003684 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3685 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003686 if (pvolume_info->mfsymlinks) {
3687 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003688 /*
3689 * Our SFU ("Services for Unix" emulation does not allow
3690 * creating symlinks but does allow reading existing SFU
3691 * symlinks (it does allow both creating and reading SFU
3692 * style mknod and FIFOs though). When "mfsymlinks" and
3693 * "sfu" are both enabled at the same time, it allows
3694 * reading both types of symlinks, but will only create
3695 * them with mfsymlinks format. This allows better
3696 * Apple compatibility (probably better for Samba too)
3697 * while still recognizing old Windows style symlinks.
3698 */
3699 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003700 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003701 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003702 }
Steve French3b795212008-11-13 19:45:32 +00003703
3704 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003705 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003706
3707 if (pvolume_info->prepath) {
3708 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
3709 if (cifs_sb->prepath == NULL)
3710 return -ENOMEM;
3711 }
3712
3713 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003714}
3715
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003716static void
3717cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003718{
Sean Finneyb9468452011-04-11 13:19:32 +00003719 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003720 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003721 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003722 kfree(volume_info->domainname);
3723 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003724 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003725}
3726
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003727void
3728cifs_cleanup_volume_info(struct smb_vol *volume_info)
3729{
3730 if (!volume_info)
3731 return;
3732 cleanup_volume_info_contents(volume_info);
3733 kfree(volume_info);
3734}
3735
3736
Steve French2d6d5892009-04-09 00:36:44 +00003737#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003738/*
3739 * cifs_build_path_to_root returns full path to root when we do not have an
3740 * exiting connection (tcon)
3741 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003742static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003743build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003744 const struct cifs_sb_info *cifs_sb)
3745{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003746 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003747 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003748 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003749
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003750 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003751 if (full_path == NULL)
3752 return ERR_PTR(-ENOMEM);
3753
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003754 strncpy(full_path, vol->UNC, unc_len);
3755 pos = full_path + unc_len;
3756
3757 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04003758 *pos = CIFS_DIR_SEP(cifs_sb);
3759 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003760 pos += pplen;
3761 }
3762
3763 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003764 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003765 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003766 return full_path;
3767}
Sean Finneydd613942011-04-11 13:19:30 +00003768
3769/*
3770 * Perform a dfs referral query for a share and (optionally) prefix
3771 *
Sean Finney046462a2011-04-11 13:19:33 +00003772 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3773 * to a string containing updated options for the submount. Otherwise it
3774 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003775 *
3776 * Returns the rc from get_dfs_path to the caller, which can be used to
3777 * determine whether there were referrals.
3778 */
3779static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003780expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003781 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003782 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003783{
3784 int rc;
3785 unsigned int num_referrals = 0;
3786 struct dfs_info3_param *referrals = NULL;
3787 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3788
3789 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3790 if (IS_ERR(full_path))
3791 return PTR_ERR(full_path);
3792
3793 /* For DFS paths, skip the first '\' of the UNC */
3794 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3795
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003796 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05003797 &num_referrals, &referrals, cifs_remap(cifs_sb));
Sean Finneydd613942011-04-11 13:19:30 +00003798
3799 if (!rc && num_referrals > 0) {
3800 char *fake_devname = NULL;
3801
3802 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3803 full_path + 1, referrals,
3804 &fake_devname);
3805
3806 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003807
Sean Finneydd613942011-04-11 13:19:30 +00003808 if (IS_ERR(mdata)) {
3809 rc = PTR_ERR(mdata);
3810 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003811 } else {
3812 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003813 rc = cifs_setup_volume_info(volume_info, mdata,
Steve Frenchc7c137b2018-06-06 17:59:29 -05003814 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00003815 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003816 kfree(fake_devname);
3817 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003818 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003819 }
3820 kfree(full_path);
3821 return rc;
3822}
Steve French2d6d5892009-04-09 00:36:44 +00003823#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003824
Jeff Layton04db79b2011-07-06 08:10:38 -04003825static int
3826cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05003827 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003829 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003830
Steve Frenchc7c137b2018-06-06 17:59:29 -05003831 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04003832 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833
Jeff Layton7586b762008-12-01 18:41:49 -05003834 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003835 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05003836 kfree(volume_info->username);
3837 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003838 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05003840 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05003842 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00003843 /* In userspace mount helper we can get user name from alternate
3844 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003845 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 }
3847
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003849 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003850 /* load_nls_default cannot return null */
3851 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003853 volume_info->local_nls = load_nls(volume_info->iocharset);
3854 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003855 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003856 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003857 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 }
3859 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003860
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003861 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003862}
3863
3864struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05003865cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04003866{
3867 int rc;
3868 struct smb_vol *volume_info;
3869
Jeff Layton6ee95422012-11-26 11:09:57 -05003870 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003871 if (!volume_info)
3872 return ERR_PTR(-ENOMEM);
3873
Steve Frenchc7c137b2018-06-06 17:59:29 -05003874 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04003875 if (rc) {
3876 cifs_cleanup_volume_info(volume_info);
3877 volume_info = ERR_PTR(rc);
3878 }
3879
3880 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003881}
3882
Aurelien Aptela6b50582016-05-25 19:59:09 +02003883static int
3884cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
3885 unsigned int xid,
3886 struct cifs_tcon *tcon,
3887 struct cifs_sb_info *cifs_sb,
3888 char *full_path)
3889{
3890 int rc;
3891 char *s;
3892 char sep, tmp;
3893
3894 sep = CIFS_DIR_SEP(cifs_sb);
3895 s = full_path;
3896
3897 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
3898 while (rc == 0) {
3899 /* skip separators */
3900 while (*s == sep)
3901 s++;
3902 if (!*s)
3903 break;
3904 /* next separator */
3905 while (*s && *s != sep)
3906 s++;
3907
3908 /*
3909 * temporarily null-terminate the path at the end of
3910 * the current component
3911 */
3912 tmp = *s;
3913 *s = 0;
3914 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3915 full_path);
3916 *s = tmp;
3917 }
3918 return rc;
3919}
3920
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003921int
Al Viro2c6292a2011-06-17 09:05:48 -04003922cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003923{
Jeff Layton1daaae82012-03-21 06:30:40 -04003924 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003925 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003926 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00003927 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003928 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003929 char *full_path;
3930 struct tcon_link *tlink;
3931#ifdef CONFIG_CIFS_DFS_UPCALL
3932 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003933#endif
Al Virodd854462011-06-17 08:24:42 -04003934
Jeff Layton20547492011-07-09 12:21:07 -04003935#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003936try_mount_again:
3937 /* cleanup activities if we're chasing a referral */
3938 if (referral_walks_count) {
3939 if (tcon)
3940 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003941 else if (ses)
3942 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003943
Sachin Prabhu1dfd18d2015-06-16 16:36:17 +01003944 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
3945
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003946 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003947 }
3948#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003949 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003950 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003951 ses = NULL;
3952 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003953 full_path = NULL;
3954 tlink = NULL;
3955
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003956 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957
Jeff Layton63c038c2008-12-01 18:41:46 -05003958 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003959 server = cifs_get_tcp_session(volume_info);
3960 if (IS_ERR(server)) {
3961 rc = PTR_ERR(server);
Jeff Layton63c038c2008-12-01 18:41:46 -05003962 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 }
Steve French141891f2016-09-23 00:44:16 -05003964 if ((volume_info->max_credits < 20) ||
3965 (volume_info->max_credits > 60000))
3966 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
3967 else
3968 server->max_credits = volume_info->max_credits;
Jeff Layton36988c72010-04-24 07:57:43 -04003969 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003970 ses = cifs_get_smb_ses(server, volume_info);
3971 if (IS_ERR(ses)) {
3972 rc = PTR_ERR(ses);
3973 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04003974 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975 }
Steve French50c2f752007-07-13 00:33:32 +00003976
Steve Frenchb618f002015-11-03 09:15:03 -06003977 if ((volume_info->persistent == true) && ((ses->server->capabilities &
3978 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
3979 cifs_dbg(VFS, "persistent handles not supported by server\n");
3980 rc = -EOPNOTSUPP;
3981 goto mount_fail_check;
3982 }
Steve French592fafe2015-11-03 10:08:53 -06003983
Jeff Laytond00c28d2010-04-24 07:57:44 -04003984 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003985 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003986 if (IS_ERR(tcon)) {
3987 rc = PTR_ERR(tcon);
3988 tcon = NULL;
Mark Syms40920c22016-11-29 11:36:46 +00003989 if (rc == -EACCES)
3990 goto mount_fail_check;
3991
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003992 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003993 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003994
Steve Frenchce558b02018-05-31 19:16:54 -05003995#ifdef CONFIG_CIFS_SMB311
3996 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
3997 if (tcon->posix_extensions)
3998 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
3999#endif /* SMB3.11 */
4000
Steve French6848b732011-05-26 18:38:54 +00004001 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004002 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00004003 /* reset of caps checks mount to see if unix extensions
4004 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04004005 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00004006 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4007 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4008 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
4009 rc = -EACCES;
4010 goto mount_fail_check;
4011 }
4012 } else
4013 tcon->unix_ext = 0; /* server does not support them */
4014
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004015 /* do not care if a following call succeed - informational */
Aurelien Aptelb327a712018-01-24 13:46:10 +01004016 if (!tcon->pipe && server->ops->qfs_tcon)
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004017 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00004018
Pavel Shilovsky24985c52012-09-18 16:20:28 -07004019 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
4020 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04004021
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004022remote_path_check:
Sean Finneyc1508ca2011-04-11 13:19:31 +00004023#ifdef CONFIG_CIFS_DFS_UPCALL
4024 /*
4025 * Perform an unconditional check for whether there are DFS
4026 * referrals for this path without prefix, to provide support
4027 * for DFS referrals from w2k8 servers which don't seem to respond
4028 * with PATH_NOT_COVERED to requests that include the prefix.
4029 * Chase the referral if found, otherwise continue normally.
4030 */
4031 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004032 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
4033 false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004034 if (!refrc) {
4035 referral_walks_count++;
4036 goto try_mount_again;
4037 }
4038 }
4039#endif
4040
Steve Frenchf87d39d2011-05-27 03:50:55 +00004041 /* check if a whole path is not remote */
Jeff Layton70945642011-03-14 13:48:08 -04004042 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004043 if (!server->ops->is_path_accessible) {
4044 rc = -ENOSYS;
4045 goto mount_fail_check;
4046 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004047 /*
4048 * cifs_build_path_to_root works only when we have a valid tcon
4049 */
Sachin Prabhu374402a2016-12-15 12:31:19 +05304050 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon,
4051 tcon->Flags & SMB_SHARE_IS_IN_DFS);
Igor Mammedove4cce942009-02-10 14:10:26 +03004052 if (full_path == NULL) {
4053 rc = -ENOMEM;
4054 goto mount_fail_check;
4055 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004056 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4057 full_path);
Jeff Layton03ceace2010-12-06 21:07:33 -05004058 if (rc != 0 && rc != -EREMOTE) {
Igor Mammedove4cce942009-02-10 14:10:26 +03004059 kfree(full_path);
4060 goto mount_fail_check;
4061 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004062
Sachin Prabhud1713562016-09-06 13:22:34 +01004063 if (rc != -EREMOTE) {
4064 rc = cifs_are_all_path_components_accessible(server,
Aurelien Aptela6b50582016-05-25 19:59:09 +02004065 xid, tcon, cifs_sb,
4066 full_path);
Sachin Prabhud1713562016-09-06 13:22:34 +01004067 if (rc != 0) {
4068 cifs_dbg(VFS, "cannot query dirs between root and final path, "
4069 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4070 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4071 rc = 0;
4072 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004073 }
Igor Mammedove4cce942009-02-10 14:10:26 +03004074 kfree(full_path);
4075 }
4076
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004077 /* get referral if needed */
4078 if (rc == -EREMOTE) {
Steve Frenchd036f502009-04-03 03:12:08 +00004079#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004080 if (referral_walks_count > MAX_NESTED_LINKS) {
4081 /*
4082 * BB: when we implement proper loop detection,
4083 * we will remove this check. But now we need it
4084 * to prevent an indefinite loop if 'DFS tree' is
4085 * misconfigured (i.e. has loops).
4086 */
4087 rc = -ELOOP;
4088 goto mount_fail_check;
4089 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004090
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004091 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04004092
Sean Finneydd613942011-04-11 13:19:30 +00004093 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004094 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004095 goto try_mount_again;
4096 }
Sean Finneydd613942011-04-11 13:19:30 +00004097 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00004098#else /* No DFS support, return error on mount */
4099 rc = -EOPNOTSUPP;
4100#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004101 }
4102
Jeff Layton9d002df2010-10-06 19:51:11 -04004103 if (rc)
4104 goto mount_fail_check;
4105
4106 /* now, hang the tcon off of the superblock */
4107 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
4108 if (tlink == NULL) {
4109 rc = -ENOMEM;
4110 goto mount_fail_check;
4111 }
4112
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004113 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004114 tlink->tl_tcon = tcon;
4115 tlink->tl_time = jiffies;
4116 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4117 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4118
Jeff Layton413e6612010-10-28 13:33:38 -04004119 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004120 spin_lock(&cifs_sb->tlink_tree_lock);
4121 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4122 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04004123
Jeff Laytonda472fc2012-03-23 14:40:53 -04004124 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004125 TLINK_IDLE_EXPIRE);
4126
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004127mount_fail_check:
4128 /* on error free sesinfo and tcon struct if needed */
4129 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004130 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03004131 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004132 if (tcon)
4133 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004134 else if (ses)
4135 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004136 else
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004137 cifs_put_tcp_session(server, 0);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004138 }
4139
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004140out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004141 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 return rc;
4143}
4144
Jeff Layton8d1bca32011-06-11 21:17:10 -04004145/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01004146 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04004147 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04004149CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00004150 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 const struct nls_table *nls_codepage)
4152{
4153 struct smb_hdr *smb_buffer;
4154 struct smb_hdr *smb_buffer_response;
4155 TCONX_REQ *pSMB;
4156 TCONX_RSP *pSMBr;
4157 unsigned char *bcc_ptr;
4158 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05004159 int length;
4160 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161
4162 if (ses == NULL)
4163 return -EIO;
4164
4165 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00004166 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00004168
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 smb_buffer_response = smb_buffer;
4170
4171 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
4172 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07004173
Pavel Shilovsky88257362012-05-23 14:01:59 +04004174 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 smb_buffer->Uid = ses->Suid;
4176 pSMB = (TCONX_REQ *) smb_buffer;
4177 pSMBr = (TCONX_RSP *) smb_buffer_response;
4178
4179 pSMB->AndXCommand = 0xFF;
4180 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01004182 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08004183 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00004184 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08004185 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00004186 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08004187 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004188 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08004189 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
4190 specified as required (when that support is added to
4191 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00004192 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08004193 by Samba (not sure whether other servers allow
4194 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00004195#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04004196 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05004197 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05004198 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00004199 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05004200 SECMODE_PW_ENCRYPT ? true : false,
4201 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00004202 else
4203#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06004204 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05004205 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05004206 if (rc) {
4207 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
4208 __func__, rc);
4209 cifs_buf_release(smb_buffer);
4210 return rc;
4211 }
Steve Frencheeac8042006-01-13 21:34:58 -08004212
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004213 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004214 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00004215 /* must align unicode strings */
4216 *bcc_ptr = 0; /* null byte password */
4217 bcc_ptr++;
4218 }
Steve Frencheeac8042006-01-13 21:34:58 -08004219 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220
Jeff Layton38d77c52013-05-26 07:01:00 -04004221 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4223
4224 if (ses->capabilities & CAP_STATUS32) {
4225 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
4226 }
4227 if (ses->capabilities & CAP_DFS) {
4228 smb_buffer->Flags2 |= SMBFLG2_DFS;
4229 }
4230 if (ses->capabilities & CAP_UNICODE) {
4231 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
4232 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06004233 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004234 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004235 (/* server len*/ + 256 /* share len */), nls_codepage);
4236 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237 bcc_ptr += 2; /* skip trailing null */
4238 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239 strcpy(bcc_ptr, tree);
4240 bcc_ptr += strlen(tree) + 1;
4241 }
4242 strcpy(bcc_ptr, "?????");
4243 bcc_ptr += strlen("?????");
4244 bcc_ptr += 1;
4245 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004246 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4247 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 pSMB->ByteCount = cpu_to_le16(count);
4249
Steve French133672e2007-11-13 22:41:37 +00004250 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004251 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01004254 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004255 bool is_unicode;
4256
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004258 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 tcon->tid = smb_buffer_response->Tid;
4260 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004261 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004262 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004263 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4264 is_unicode = true;
4265 else
4266 is_unicode = false;
4267
Jeff Laytoncc20c032009-04-30 07:16:21 -04004268
Steve French50c2f752007-07-13 00:33:32 +00004269 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004270 if (length == 3) {
4271 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4272 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004273 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01004274 tcon->ipc = true;
4275 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00004276 }
4277 } else if (length == 2) {
4278 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4279 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05004280 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004281 }
4282 }
Steve French50c2f752007-07-13 00:33:32 +00004283 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004284 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05004285 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04004286
4287 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004288 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004289 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004290 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004291 nls_codepage);
4292
Joe Perchesf96637b2013-05-04 22:12:25 -05004293 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004294
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004295 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004296 (smb_buffer_response->WordCount == 7))
4297 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004298 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4299 else
4300 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05004301 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302 }
4303
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004304 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 return rc;
4306}
4307
Al Viro2e32cf52013-10-03 12:53:37 -04004308static void delayed_free(struct rcu_head *p)
4309{
4310 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
4311 unload_nls(sbi->local_nls);
4312 kfree(sbi);
4313}
4314
Al Viro2a9b9952011-06-17 09:27:16 -04004315void
4316cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317{
Jeff Laytonb647c352010-10-28 11:16:44 -04004318 struct rb_root *root = &cifs_sb->tlink_tree;
4319 struct rb_node *node;
4320 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321
Jeff Layton2de970f2010-10-06 19:51:12 -04004322 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4323
Jeff Laytonb647c352010-10-28 11:16:44 -04004324 spin_lock(&cifs_sb->tlink_tree_lock);
4325 while ((node = rb_first(root))) {
4326 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4327 cifs_get_tlink(tlink);
4328 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4329 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004330
Jeff Laytonb647c352010-10-28 11:16:44 -04004331 spin_unlock(&cifs_sb->tlink_tree_lock);
4332 cifs_put_tlink(tlink);
4333 spin_lock(&cifs_sb->tlink_tree_lock);
4334 }
4335 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004336
Al Virod757d712011-06-17 09:42:43 -04004337 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02004338 kfree(cifs_sb->prepath);
Al Viro2e32cf52013-10-03 12:53:37 -04004339 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00004340}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004342int
4343cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344{
4345 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004346 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004348 if (!server->ops->need_neg || !server->ops->negotiate)
4349 return -ENOSYS;
4350
Jeff Layton198b5682010-04-24 07:57:48 -04004351 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004352 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04004353 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354
Pavel Shilovsky45275782012-05-17 17:53:29 +04004355 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004356
4357 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04004358 if (rc == 0) {
4359 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004360 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004361 server->tcpStatus = CifsGood;
4362 else
4363 rc = -EHOSTDOWN;
4364 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 }
Steve French26b994f2008-08-06 05:11:33 +00004366
Jeff Layton198b5682010-04-24 07:57:48 -04004367 return rc;
4368}
Steve French26b994f2008-08-06 05:11:33 +00004369
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004370int
4371cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
4372 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04004373{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004374 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04004375 struct TCP_Server_Info *server = ses->server;
4376
Jeff Layton198b5682010-04-24 07:57:48 -04004377 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004378 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004379 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00004380
Joe Perchesf96637b2013-05-04 22:12:25 -05004381 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00004382 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004383
Shu Wangf5c4ba82017-09-08 18:48:33 +08004384 if (ses->auth_key.response) {
Steve French2a182872018-03-29 12:16:34 -05004385 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
Shu Wangf5c4ba82017-09-08 18:48:33 +08004386 ses->auth_key.response);
4387 kfree(ses->auth_key.response);
4388 ses->auth_key.response = NULL;
4389 ses->auth_key.len = 0;
4390 }
4391
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004392 if (server->ops->sess_setup)
4393 rc = server->ops->sess_setup(xid, ses, nls_info);
4394
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05004395 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05004396 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004397
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 return rc;
4399}
4400
Jeff Layton8a8798a2012-01-17 16:09:15 -05004401static int
4402cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4403{
Jeff Layton3f618222013-06-12 19:52:14 -05004404 vol->sectype = ses->sectype;
4405
4406 /* krb5 is special, since we don't need username or pw */
4407 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05004408 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05004409
4410 return cifs_set_cifscreds(vol, ses);
4411}
4412
Steve French96daf2b2011-05-27 04:34:02 +00004413static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004414cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04004415{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004416 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004417 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4418 struct cifs_ses *ses;
4419 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004420 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004421
4422 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004423 if (vol_info == NULL)
4424 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004425
Jeff Layton9d002df2010-10-06 19:51:11 -04004426 vol_info->local_nls = cifs_sb->local_nls;
4427 vol_info->linux_uid = fsuid;
4428 vol_info->cred_uid = fsuid;
4429 vol_info->UNC = master_tcon->treeName;
4430 vol_info->retry = master_tcon->retry;
4431 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05004432 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04004433 vol_info->local_lease = master_tcon->local_lease;
4434 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004435 vol_info->sectype = master_tcon->ses->sectype;
4436 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004437
Jeff Layton8a8798a2012-01-17 16:09:15 -05004438 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4439 if (rc) {
4440 tcon = ERR_PTR(rc);
4441 goto out;
4442 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004443
4444 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304445 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004446 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304447 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004448
4449 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4450 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004451 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004452 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04004453 goto out;
4454 }
4455
4456 tcon = cifs_get_tcon(ses, vol_info);
4457 if (IS_ERR(tcon)) {
4458 cifs_put_smb_ses(ses);
4459 goto out;
4460 }
4461
Steve Frenchce558b02018-05-31 19:16:54 -05004462#ifdef CONFIG_CIFS_SMB311
4463 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4464 if (tcon->posix_extensions)
4465 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4466#endif /* SMB3.11 */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004467 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004468 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05004469
Jeff Layton9d002df2010-10-06 19:51:11 -04004470out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004471 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01004472 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004473 kfree(vol_info);
4474
4475 return tcon;
4476}
4477
Steve French96daf2b2011-05-27 04:34:02 +00004478struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004479cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4480{
4481 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4482}
4483
Jeff Laytonb647c352010-10-28 11:16:44 -04004484/* find and return a tlink with given uid */
4485static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004486tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04004487{
4488 struct rb_node *node = root->rb_node;
4489 struct tcon_link *tlink;
4490
4491 while (node) {
4492 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4493
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004494 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004495 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004496 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004497 node = node->rb_right;
4498 else
4499 return tlink;
4500 }
4501 return NULL;
4502}
4503
4504/* insert a tcon_link into the tree */
4505static void
4506tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4507{
4508 struct rb_node **new = &(root->rb_node), *parent = NULL;
4509 struct tcon_link *tlink;
4510
4511 while (*new) {
4512 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4513 parent = *new;
4514
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004515 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004516 new = &((*new)->rb_left);
4517 else
4518 new = &((*new)->rb_right);
4519 }
4520
4521 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4522 rb_insert_color(&new_tlink->tl_rbnode, root);
4523}
4524
Jeff Layton9d002df2010-10-06 19:51:11 -04004525/*
4526 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4527 * current task.
4528 *
4529 * If the superblock doesn't refer to a multiuser mount, then just return
4530 * the master tcon for the mount.
4531 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304532 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004533 * exists, then check to see if it's pending construction. If it is then wait
4534 * for construction to complete. Once it's no longer pending, check to see if
4535 * it failed and either return an error or retry construction, depending on
4536 * the timeout.
4537 *
4538 * If one doesn't exist then insert a new tcon_link struct into the tree and
4539 * try to construct a new one.
4540 */
4541struct tcon_link *
4542cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4543{
4544 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004545 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004546 struct tcon_link *tlink, *newtlink;
4547
4548 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4549 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4550
4551 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004552 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004553 if (tlink)
4554 cifs_get_tlink(tlink);
4555 spin_unlock(&cifs_sb->tlink_tree_lock);
4556
4557 if (tlink == NULL) {
4558 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4559 if (newtlink == NULL)
4560 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004561 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004562 newtlink->tl_tcon = ERR_PTR(-EACCES);
4563 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4564 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4565 cifs_get_tlink(newtlink);
4566
Jeff Layton9d002df2010-10-06 19:51:11 -04004567 spin_lock(&cifs_sb->tlink_tree_lock);
4568 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004569 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004570 if (tlink) {
4571 cifs_get_tlink(tlink);
4572 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004573 kfree(newtlink);
4574 goto wait_for_construction;
4575 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004576 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004577 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4578 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004579 } else {
4580wait_for_construction:
4581 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04004582 TASK_INTERRUPTIBLE);
4583 if (ret) {
4584 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10004585 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04004586 }
4587
4588 /* if it's good, return it */
4589 if (!IS_ERR(tlink->tl_tcon))
4590 return tlink;
4591
4592 /* return error if we tried this already recently */
4593 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4594 cifs_put_tlink(tlink);
4595 return ERR_PTR(-EACCES);
4596 }
4597
4598 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4599 goto wait_for_construction;
4600 }
4601
4602 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4603 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4604 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4605
4606 if (IS_ERR(tlink->tl_tcon)) {
4607 cifs_put_tlink(tlink);
4608 return ERR_PTR(-EACCES);
4609 }
4610
4611 return tlink;
4612}
Jeff Layton2de970f2010-10-06 19:51:12 -04004613
4614/*
4615 * periodic workqueue job that scans tcon_tree for a superblock and closes
4616 * out tcons.
4617 */
4618static void
4619cifs_prune_tlinks(struct work_struct *work)
4620{
4621 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4622 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004623 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00004624 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04004625 struct rb_node *tmp;
4626 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004627
Jeff Laytonb647c352010-10-28 11:16:44 -04004628 /*
4629 * Because we drop the spinlock in the loop in order to put the tlink
4630 * it's not guarded against removal of links from the tree. The only
4631 * places that remove entries from the tree are this function and
4632 * umounts. Because this function is non-reentrant and is canceled
4633 * before umount can proceed, this is safe.
4634 */
4635 spin_lock(&cifs_sb->tlink_tree_lock);
4636 node = rb_first(root);
4637 while (node != NULL) {
4638 tmp = node;
4639 node = rb_next(tmp);
4640 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4641
4642 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4643 atomic_read(&tlink->tl_count) != 0 ||
4644 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4645 continue;
4646
4647 cifs_get_tlink(tlink);
4648 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4649 rb_erase(tmp, root);
4650
Jeff Layton2de970f2010-10-06 19:51:12 -04004651 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004652 cifs_put_tlink(tlink);
4653 spin_lock(&cifs_sb->tlink_tree_lock);
4654 }
4655 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004656
Jeff Laytonda472fc2012-03-23 14:40:53 -04004657 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004658 TLINK_IDLE_EXPIRE);
4659}