blob: 803a7663da2a948aab5e4ac07092ab5ea5581c37 [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>
24#include <linux/list.h>
25#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090026#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/pagemap.h>
28#include <linux/ctype.h>
29#include <linux/utsname.h>
30#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070031#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070032#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000033#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070034#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080035#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040036#include <linux/namei.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <asm/uaccess.h>
38#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040039#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040040#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050041#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000042#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040043#include <linux/parser.h>
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "cifspdu.h"
46#include "cifsglob.h"
47#include "cifsproto.h"
48#include "cifs_unicode.h"
49#include "cifs_debug.h"
50#include "cifs_fs_sb.h"
Paulo Alcantarafb713a12018-11-20 15:16:36 -020051#include "dns_resolve.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include "ntlmssp.h"
53#include "nterr.h"
54#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053055#include "fscache.h"
Pavel Shilovsky48f95262016-11-04 11:50:31 -070056#ifdef CONFIG_CIFS_SMB2
57#include "smb2proto.h"
58#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60#define CIFS_PORT 445
61#define RFC1001_PORT 139
62
Linus Torvalds1da177e2005-04-16 15:20:36 -070063extern mempool_t *cifs_req_poolp;
64
Jeff Layton2de970f2010-10-06 19:51:12 -040065/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040066#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040067#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040068
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040069enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040070 /* Mount options that take no arguments */
71 Opt_user_xattr, Opt_nouser_xattr,
72 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040073 Opt_forcegid, Opt_noforcegid,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040074 Opt_noblocksend, Opt_noautotune,
75 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
Steve French2baa2682014-09-27 02:19:01 -050076 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040077 Opt_mapchars, Opt_nomapchars, Opt_sfu,
78 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
79 Opt_noposixpaths, Opt_nounix,
80 Opt_nocase,
81 Opt_brl, Opt_nobrl,
Steve French95932652016-09-23 01:36:34 -050082 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040083 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
84 Opt_nohard, Opt_nosoft,
85 Opt_nointr, Opt_intr,
86 Opt_nostrictsync, Opt_strictsync,
87 Opt_serverino, Opt_noserverino,
88 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
89 Opt_acl, Opt_noacl, Opt_locallease,
Jeff Layton1b359202012-09-19 15:20:27 -070090 Opt_sign, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040091 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -040092 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -050093 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -060094 Opt_resilient, Opt_noresilient,
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,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400102
103 /* Mount options which take string value */
104 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400105 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400106 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400107 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400108
109 /* Mount options to be ignored */
110 Opt_ignore,
111
112 /* Options which could be blank */
113 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100114 Opt_blank_user,
115 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400116
117 Opt_err
118};
119
120static const match_table_t cifs_mount_option_tokens = {
121
122 { Opt_user_xattr, "user_xattr" },
123 { Opt_nouser_xattr, "nouser_xattr" },
124 { Opt_forceuid, "forceuid" },
125 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400126 { Opt_forcegid, "forcegid" },
127 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400128 { Opt_noblocksend, "noblocksend" },
129 { Opt_noautotune, "noautotune" },
130 { Opt_hard, "hard" },
131 { Opt_soft, "soft" },
132 { Opt_perm, "perm" },
133 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500134 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400135 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500136 { Opt_mapposix, "mapposix" }, /* SFM style */
137 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400138 { Opt_sfu, "sfu" },
139 { Opt_nosfu, "nosfu" },
140 { Opt_nodfs, "nodfs" },
141 { Opt_posixpaths, "posixpaths" },
142 { Opt_noposixpaths, "noposixpaths" },
143 { Opt_nounix, "nounix" },
144 { Opt_nounix, "nolinux" },
145 { Opt_nocase, "nocase" },
146 { Opt_nocase, "ignorecase" },
147 { Opt_brl, "brl" },
148 { Opt_nobrl, "nobrl" },
149 { Opt_nobrl, "nolock" },
150 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400151 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400152 { Opt_setuids, "setuids" },
153 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500154 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400155 { Opt_dynperm, "dynperm" },
156 { Opt_nodynperm, "nodynperm" },
157 { Opt_nohard, "nohard" },
158 { Opt_nosoft, "nosoft" },
159 { Opt_nointr, "nointr" },
160 { Opt_intr, "intr" },
161 { Opt_nostrictsync, "nostrictsync" },
162 { Opt_strictsync, "strictsync" },
163 { Opt_serverino, "serverino" },
164 { Opt_noserverino, "noserverino" },
165 { Opt_rwpidforward, "rwpidforward" },
166 { Opt_cifsacl, "cifsacl" },
167 { Opt_nocifsacl, "nocifsacl" },
168 { Opt_acl, "acl" },
169 { Opt_noacl, "noacl" },
170 { Opt_locallease, "locallease" },
171 { Opt_sign, "sign" },
172 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400173 { Opt_noac, "noac" },
174 { Opt_fsc, "fsc" },
175 { Opt_mfsymlinks, "mfsymlinks" },
176 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400177 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400178 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500179 { Opt_persistent, "persistenthandles"},
180 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600181 { Opt_resilient, "resilienthandles"},
182 { Opt_noresilient, "noresilienthandles"},
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400183
184 { Opt_backupuid, "backupuid=%s" },
185 { Opt_backupgid, "backupgid=%s" },
186 { Opt_uid, "uid=%s" },
187 { Opt_cruid, "cruid=%s" },
188 { Opt_gid, "gid=%s" },
189 { Opt_file_mode, "file_mode=%s" },
190 { Opt_dirmode, "dirmode=%s" },
191 { Opt_dirmode, "dir_mode=%s" },
192 { Opt_port, "port=%s" },
193 { Opt_rsize, "rsize=%s" },
194 { Opt_wsize, "wsize=%s" },
195 { Opt_actimeo, "actimeo=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600196 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500197 { Opt_max_credits, "max_credits=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400198
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100199 { Opt_blank_user, "user=" },
200 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400201 { Opt_user, "user=%s" },
202 { Opt_user, "username=%s" },
203 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100204 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400205 { Opt_pass, "pass=%s" },
206 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100207 { Opt_blank_ip, "ip=" },
208 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400209 { Opt_ip, "ip=%s" },
210 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400211 { Opt_ignore, "unc=%s" },
212 { Opt_ignore, "target=%s" },
213 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400214 { Opt_domain, "dom=%s" },
215 { Opt_domain, "domain=%s" },
216 { Opt_domain, "workgroup=%s" },
217 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400218 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400219 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400220 { Opt_netbiosname, "netbiosname=%s" },
221 { Opt_servern, "servern=%s" },
222 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400223 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400224 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400225 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400226
227 { Opt_ignore, "cred" },
228 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400229 { Opt_ignore, "cred=%s" },
230 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400231 { Opt_ignore, "guest" },
232 { Opt_ignore, "rw" },
233 { Opt_ignore, "ro" },
234 { Opt_ignore, "suid" },
235 { Opt_ignore, "nosuid" },
236 { Opt_ignore, "exec" },
237 { Opt_ignore, "noexec" },
238 { Opt_ignore, "nodev" },
239 { Opt_ignore, "noauto" },
240 { Opt_ignore, "dev" },
241 { Opt_ignore, "mand" },
242 { Opt_ignore, "nomand" },
243 { Opt_ignore, "_netdev" },
244
245 { Opt_err, NULL }
246};
247
248enum {
249 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
250 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400251 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
252 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400253 Opt_sec_none,
254
255 Opt_sec_err
256};
257
258static const match_table_t cifs_secflavor_tokens = {
259 { Opt_sec_krb5, "krb5" },
260 { Opt_sec_krb5i, "krb5i" },
261 { Opt_sec_krb5p, "krb5p" },
262 { Opt_sec_ntlmsspi, "ntlmsspi" },
263 { Opt_sec_ntlmssp, "ntlmssp" },
264 { Opt_ntlm, "ntlm" },
265 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400266 { Opt_sec_ntlmv2, "nontlm" },
267 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400268 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400269 { Opt_sec_lanman, "lanman" },
270 { Opt_sec_none, "none" },
271
272 { Opt_sec_err, NULL }
273};
274
Jeff Layton15b6a472012-05-16 07:50:15 -0400275/* cache flavors */
276enum {
277 Opt_cache_loose,
278 Opt_cache_strict,
279 Opt_cache_none,
280 Opt_cache_err
281};
282
283static const match_table_t cifs_cacheflavor_tokens = {
284 { Opt_cache_loose, "loose" },
285 { Opt_cache_strict, "strict" },
286 { Opt_cache_none, "none" },
287 { Opt_cache_err, NULL }
288};
289
Jeff Layton23db65f2012-05-15 12:20:51 -0400290static const match_table_t cifs_smb_version_tokens = {
291 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600292 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000293 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500294 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500295 { Smb_302, SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600296#ifdef CONFIG_CIFS_SMB311
297 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500298 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600299#endif /* SMB311 */
300 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400301};
302
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300303static int ip_connect(struct TCP_Server_Info *server);
304static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400305static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400306static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400307static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
308 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Jeff Laytond5c56052008-12-01 18:42:33 -0500310/*
Paulo Alcantarafb713a12018-11-20 15:16:36 -0200311 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
312 * get their ip addresses changed at some point.
313 *
314 * This should be called with server->srv_mutex held.
315 */
316#ifdef CONFIG_CIFS_DFS_UPCALL
317static int reconn_set_ipaddr(struct TCP_Server_Info *server)
318{
319 int rc;
320 int len;
321 char *unc, *ipaddr = NULL;
322
323 if (!server->hostname)
324 return -EINVAL;
325
326 len = strlen(server->hostname) + 3;
327
328 unc = kmalloc(len, GFP_KERNEL);
329 if (!unc) {
330 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
331 return -ENOMEM;
332 }
333 snprintf(unc, len, "\\\\%s", server->hostname);
334
335 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
336 kfree(unc);
337
338 if (rc < 0) {
339 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
340 __func__, server->hostname, rc);
341 return rc;
342 }
343
Ronnie Sahlberg3f9b0d02020-04-21 12:37:39 +1000344 spin_lock(&cifs_tcp_ses_lock);
Paulo Alcantarafb713a12018-11-20 15:16:36 -0200345 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
346 strlen(ipaddr));
Ronnie Sahlberg3f9b0d02020-04-21 12:37:39 +1000347 spin_unlock(&cifs_tcp_ses_lock);
Paulo Alcantarafb713a12018-11-20 15:16:36 -0200348 kfree(ipaddr);
349
350 return !rc ? -1 : 0;
351}
352#else
353static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
354{
355 return 0;
356}
357#endif
358
359/*
Jeff Laytond5c56052008-12-01 18:42:33 -0500360 * cifs tcp session reconnection
361 *
362 * mark tcp session as reconnecting so temporarily locked
363 * mark all smb sessions as reconnecting for tcp session
364 * reconnect tcp session
365 * wake up waiters on reconnection? - (not needed currently)
366 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400367int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368cifs_reconnect(struct TCP_Server_Info *server)
369{
370 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500371 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000372 struct cifs_ses *ses;
373 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000374 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400375 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000378 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000379 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 next time through the loop */
381 spin_unlock(&GlobalMid_Lock);
382 return rc;
383 } else
384 server->tcpStatus = CifsNeedReconnect;
385 spin_unlock(&GlobalMid_Lock);
386 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400387#ifdef CONFIG_CIFS_SMB2
388 server->max_read = 0;
389#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Joe Perchesf96637b2013-05-04 22:12:25 -0500391 cifs_dbg(FYI, "Reconnecting tcp session\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
393 /* before reconnecting the tcp session, mark the smb session (uid)
394 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500395 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
396 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530397 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500398 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000399 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500400 ses->need_reconnect = true;
401 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500402 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000403 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500404 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530407 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500408
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500410 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500411 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000412 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500413 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
414 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800415 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500416 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
417 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 sock_release(server->ssocket);
419 server->ssocket = NULL;
420 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500421 server->sequence_number = 0;
422 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500423 kfree(server->session_key.response);
424 server->session_key.response = NULL;
425 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000426 server->lstrp = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500428 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400429 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500430 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500432 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
433 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400434 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
435 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400436 list_move(&mid_entry->qhead, &retry_list);
437 }
438 spin_unlock(&GlobalMid_Lock);
Rabin Vincent820962d2015-12-23 07:32:41 +0100439 mutex_unlock(&server->srv_mutex);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400440
Joe Perchesf96637b2013-05-04 22:12:25 -0500441 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400442 list_for_each_safe(tmp, tmp2, &retry_list) {
443 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500444 list_del_init(&mid_entry->qhead);
445 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400448 do {
Steve French6c3d8902006-07-31 22:46:20 +0000449 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300450
451 /* we should try only the port we connected to before */
Jeff Layton73e216a2013-09-05 08:38:10 -0400452 mutex_lock(&server->srv_mutex);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300453 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000454 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500455 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantarafb713a12018-11-20 15:16:36 -0200456 rc = reconn_set_ipaddr(server);
457 if (rc) {
458 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
459 __func__, rc);
460 }
Federico Sauter4afe2602015-03-17 17:45:28 +0100461 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700462 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 } else {
464 atomic_inc(&tcpSesReconnectCount);
465 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000466 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000467 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000468 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100469 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400471 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500472
Sachin Prabhub8c60012016-10-20 19:52:24 -0400473 if (server->tcpStatus == CifsNeedNegotiate)
474 mod_delayed_work(cifsiod_wq, &server->echo, 0);
475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 return rc;
477}
478
Jeff Laytonc74093b2011-01-11 07:24:23 -0500479static void
480cifs_echo_request(struct work_struct *work)
481{
482 int rc;
483 struct TCP_Server_Info *server = container_of(work,
484 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400485 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500486
Jeff Layton247ec9b2011-02-04 17:09:50 -0500487 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400488 * If we need to renegotiate, set echo interval to zero to
489 * immediately call echo service where we can renegotiate.
490 */
491 if (server->tcpStatus == CifsNeedNegotiate)
492 echo_interval = 0;
493 else
494 echo_interval = server->echo_interval;
495
496 /*
497 * We cannot send an echo if it is disabled.
498 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500499 */
Steve French4fcd1812016-06-22 20:12:05 -0500500
501 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400502 server->tcpStatus == CifsExiting ||
503 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400504 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600505 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500506 goto requeue_echo;
507
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400508 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500509 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500510 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
511 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500512
513requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400514 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500515}
516
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400517static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400518allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400519{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400520 if (!server->bigbuf) {
521 server->bigbuf = (char *)cifs_buf_get();
522 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500523 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400524 msleep(3000);
525 /* retry will check if exiting */
526 return false;
527 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400528 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400529 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400530 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400531 }
532
Jeff Layton2a37ef92011-10-19 15:29:23 -0400533 if (!server->smallbuf) {
534 server->smallbuf = (char *)cifs_small_buf_get();
535 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500536 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400537 msleep(1000);
538 /* retry will check if exiting */
539 return false;
540 }
541 /* beginning of smb buffer is cleared in our buf_get */
542 } else {
543 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400544 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400545 }
546
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400547 return true;
548}
549
Jeff Laytonba749e62011-10-11 06:41:32 -0400550static bool
551server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400552{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300553 /*
Ronnie Sahlbergf0fff9a2019-07-06 06:52:46 +1000554 * We need to wait 3 echo intervals to make sure we handle such
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300555 * situations right:
556 * 1s client sends a normal SMB request
Ronnie Sahlbergf0fff9a2019-07-06 06:52:46 +1000557 * 3s client gets a response
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300558 * 30s echo workqueue job pops, and decides we got a response recently
559 * and don't need to send another
560 * ...
561 * 65s kernel_recvmsg times out, and we see that we haven't gotten
562 * a response in >60s.
563 */
Samuel Cabrero79d25ee2017-07-11 12:44:39 +0200564 if ((server->tcpStatus == CifsGood ||
565 server->tcpStatus == CifsNeedNegotiate) &&
Ronnie Sahlbergf0fff9a2019-07-06 06:52:46 +1000566 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600567 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
Ronnie Sahlbergf0fff9a2019-07-06 06:52:46 +1000568 server->hostname, (3 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400569 cifs_reconnect(server);
570 wake_up(&server->response_q);
571 return true;
572 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400573
Jeff Laytonba749e62011-10-11 06:41:32 -0400574 return false;
575}
576
Al Viro71335662016-01-09 19:54:50 -0500577static int
578cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400579{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400580 int length = 0;
581 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400582
Al Viro71335662016-01-09 19:54:50 -0500583 smb_msg->msg_control = NULL;
584 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400585
Al Viro71335662016-01-09 19:54:50 -0500586 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500587 try_to_freeze();
588
Al Viro71335662016-01-09 19:54:50 -0500589 if (server_unresponsive(server))
590 return -ECONNABORTED;
591
592 length = sock_recvmsg(server->ssocket, smb_msg, 0);
593
594 if (server->tcpStatus == CifsExiting)
595 return -ESHUTDOWN;
596
597 if (server->tcpStatus == CifsNeedReconnect) {
598 cifs_reconnect(server);
599 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400600 }
601
Al Viro71335662016-01-09 19:54:50 -0500602 if (length == -ERESTARTSYS ||
603 length == -EAGAIN ||
604 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400605 /*
606 * Minimum sleep to prevent looping, allowing socket
607 * to clear and app threads to set tcpStatus
608 * CifsNeedReconnect if server hung.
609 */
610 usleep_range(1000, 2000);
611 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400612 continue;
Al Viro71335662016-01-09 19:54:50 -0500613 }
614
615 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500616 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400617 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500618 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400619 }
620 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400621 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400622}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400623
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400624int
625cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
626 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400627{
Al Viro71335662016-01-09 19:54:50 -0500628 struct msghdr smb_msg;
629 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
630 iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400631
Al Viro71335662016-01-09 19:54:50 -0500632 return cifs_readv_from_socket(server, &smb_msg);
633}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400634
Al Viro71335662016-01-09 19:54:50 -0500635int
636cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
637 unsigned int to_read)
638{
639 struct msghdr smb_msg;
640 struct bio_vec bv = {.bv_page = page, .bv_len = to_read};
641 iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
642 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400643}
644
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400645static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400646is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400647{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400648 /*
649 * The first byte big endian of the length field,
650 * is actually not part of the length but the type
651 * with the most common, zero, as regular data.
652 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400653 switch (type) {
654 case RFC1002_SESSION_MESSAGE:
655 /* Regular SMB response */
656 return true;
657 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500658 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400659 break;
660 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500661 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400662 break;
663 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400664 /*
665 * We get this from Windows 98 instead of an error on
666 * SMB negprot response.
667 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500668 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400669 /* give server a second to clean up */
670 msleep(1000);
671 /*
672 * Always try 445 first on reconnect since we get NACK
673 * on some if we ever connected to port 139 (the NACK
674 * is since we do not begin with RFC1001 session
675 * initialize frame).
676 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400677 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400678 cifs_reconnect(server);
679 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400680 break;
681 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500682 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400683 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400684 }
685
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400686 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400687}
688
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400689void
690dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400691{
692#ifdef CONFIG_CIFS_STATS2
693 mid->when_received = jiffies;
694#endif
695 spin_lock(&GlobalMid_Lock);
696 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400697 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400698 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400699 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400700 list_del_init(&mid->qhead);
701 spin_unlock(&GlobalMid_Lock);
702}
703
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400704static void
705handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400706 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400707{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400708 if (server->ops->check_trans2 &&
709 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400710 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400711 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400712 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400713 /* Was previous buf put in mpx struct for multi-rsp? */
714 if (!mid->multiRsp) {
715 /* smb buffer will be freed by user thread */
716 if (server->large_buf)
717 server->bigbuf = NULL;
718 else
719 server->smallbuf = NULL;
720 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400721 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400722}
723
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400724static void clean_demultiplex_info(struct TCP_Server_Info *server)
725{
726 int length;
727
728 /* take it off the list, if it's not already */
729 spin_lock(&cifs_tcp_ses_lock);
730 list_del_init(&server->tcp_ses_list);
731 spin_unlock(&cifs_tcp_ses_lock);
732
733 spin_lock(&GlobalMid_Lock);
734 server->tcpStatus = CifsExiting;
735 spin_unlock(&GlobalMid_Lock);
736 wake_up_all(&server->response_q);
737
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400738 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300739 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400740 if (server->credits <= 0)
741 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300742 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400743 /*
744 * Although there should not be any requests blocked on this queue it
745 * can not hurt to be paranoid and try to wake up requests that may
746 * haven been blocked when more than 50 at time were on the wire to the
747 * same server - they now will see the session is in exit state and get
748 * out of SendReceive.
749 */
750 wake_up_all(&server->request_q);
751 /* give those requests time to exit */
752 msleep(125);
753
754 if (server->ssocket) {
755 sock_release(server->ssocket);
756 server->ssocket = NULL;
757 }
758
759 if (!list_empty(&server->pending_mid_q)) {
760 struct list_head dispose_list;
761 struct mid_q_entry *mid_entry;
762 struct list_head *tmp, *tmp2;
763
764 INIT_LIST_HEAD(&dispose_list);
765 spin_lock(&GlobalMid_Lock);
766 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
767 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500768 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400769 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400770 list_move(&mid_entry->qhead, &dispose_list);
771 }
772 spin_unlock(&GlobalMid_Lock);
773
774 /* now walk dispose list and issue callbacks */
775 list_for_each_safe(tmp, tmp2, &dispose_list) {
776 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500777 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400778 list_del_init(&mid_entry->qhead);
779 mid_entry->callback(mid_entry);
780 }
781 /* 1/8th of sec is more than enough time for them to exit */
782 msleep(125);
783 }
784
785 if (!list_empty(&server->pending_mid_q)) {
786 /*
787 * mpx threads have not exited yet give them at least the smb
788 * send timeout time for long ops.
789 *
790 * Due to delays on oplock break requests, we need to wait at
791 * least 45 seconds before giving up on a request getting a
792 * response and going ahead and killing cifsd.
793 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500794 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400795 msleep(46000);
796 /*
797 * If threads still have not exited they are probably never
798 * coming home not much else we can do but free the memory.
799 */
800 }
801
802 kfree(server->hostname);
803 kfree(server);
804
805 length = atomic_dec_return(&tcpSesAllocCount);
806 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700807 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400808}
809
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400810static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400811standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
812{
813 int length;
814 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400815 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400816
817 /* make sure this will fit in a large buffer */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400818 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500819 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400820 cifs_reconnect(server);
821 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400822 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400823 }
824
825 /* switch to large buffer if too big for a small one */
826 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
827 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400828 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400829 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400830 }
831
832 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400833 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
834 pdu_length - HEADER_SIZE(server) + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400835 if (length < 0)
836 return length;
837 server->total_read += length;
838
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400839 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400840
841 /*
842 * We know that we received enough to get to the MID as we
843 * checked the pdu_length earlier. Now check to see
844 * if the rest of the header is OK. We borrow the length
845 * var for the rest of the loop to avoid a new stack var.
846 *
847 * 48 bytes is enough to display the header and a little bit
848 * into the payload for debugging purposes.
849 */
Steve French373512e2015-12-18 13:05:30 -0600850 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400851 if (length != 0)
852 cifs_dump_mem("Bad SMB: ", buf,
853 min_t(unsigned int, server->total_read, 48));
854
Pavel Shilovsky92d7d3e2017-07-08 14:32:00 -0700855 if (server->ops->is_session_expired &&
856 server->ops->is_session_expired(buf)) {
857 cifs_reconnect(server);
858 wake_up(&server->response_q);
859 return -1;
860 }
861
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700862 if (server->ops->is_status_pending &&
863 server->ops->is_status_pending(buf, server, length))
864 return -1;
865
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500866 if (!mid)
867 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400868
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400869 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500870 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400871}
872
873static int
Al Viro7c97c202011-06-21 08:51:28 -0400874cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875{
876 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400877 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400878 unsigned int pdu_length;
879 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500880 struct task_struct *task_to_wake = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -0500884 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400885
886 length = atomic_inc_return(&tcpSesAllocCount);
887 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -0700888 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700890 set_freezable();
Eric W. Biedermana3714572019-08-16 12:33:54 -0500891 allow_kernel_signal(SIGKILL);
Jeff Layton469ee612008-10-16 18:46:39 +0000892 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700893 if (try_to_freeze())
894 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700895
Jeff Layton2a37ef92011-10-19 15:29:23 -0400896 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400897 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700898
Jeff Layton2a37ef92011-10-19 15:29:23 -0400899 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400900 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000901 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000902
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400903 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400904 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +0000905 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400906 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700907
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400908 /*
909 * The right amount was read from socket - 4 bytes,
910 * so we can now interpret the length field.
911 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400912 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -0700913
Joe Perchesf96637b2013-05-04 22:12:25 -0500914 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400915 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000916 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700917
Jeff Layton89482a52011-10-19 15:28:57 -0400918 /* make sure we have enough to get to the MID */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400919 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500920 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
921 pdu_length);
Jeff Layton89482a52011-10-19 15:28:57 -0400922 cifs_reconnect(server);
923 wake_up(&server->response_q);
924 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700925 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400926
Jeff Layton89482a52011-10-19 15:28:57 -0400927 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400928 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400929 HEADER_SIZE(server) - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -0400930 if (length < 0)
931 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400932 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -0400933
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400934 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400935
Jeff Layton44d22d82011-10-19 15:29:49 -0400936 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 Laytona52c1eb2011-10-11 06:41:32 -0400941 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -0700942 continue;
943
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400944 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -0400945 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -0700946
Steve Frenchfda35942011-01-20 18:06:34 +0000947 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500948 if (mid_entry != NULL) {
Sachin Prabhud8fd99d2017-03-03 15:41:38 -0800949 if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
950 mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
951 server->ops->handle_cancelled_mid)
952 server->ops->handle_cancelled_mid(
953 mid_entry->resp_buf,
954 server);
955
Jeff Layton2a37ef92011-10-19 15:29:23 -0400956 if (!mid_entry->multiRsp || mid_entry->multiEnd)
957 mid_entry->callback(mid_entry);
Sachin Prabhud8fd99d2017-03-03 15:41:38 -0800958 } else if (server->ops->is_oplock_break &&
959 server->ops->is_oplock_break(buf, server)) {
960 cifs_dbg(FYI, "Received oplock break\n");
961 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -0500962 cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
963 atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400964 cifs_dump_mem("Received Data is: ", buf,
965 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +0000966#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400967 if (server->ops->dump_detail)
968 server->ops->dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +0000969 cifs_dump_mids(server);
970#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +0000971
Steve Frenche4eb2952005-04-28 22:41:09 -0700972 }
973 } /* end while !EXITING */
974
Justin P. Mattockfd62cb72011-02-24 22:15:02 -0800975 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -0400976 cifs_buf_release(server->bigbuf);
977 if (server->smallbuf) /* no sense logging a debug message if NULL */
978 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500980 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400981 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500982
983 /* if server->tsk was NULL then wait for a signal before exiting */
984 if (!task_to_wake) {
985 set_current_state(TASK_INTERRUPTIBLE);
986 while (!signal_pending(current)) {
987 schedule();
988 set_current_state(TASK_INTERRUPTIBLE);
989 }
990 set_current_state(TASK_RUNNING);
991 }
992
Jeff Layton0468a2c2008-12-01 07:09:35 -0500993 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994}
995
Jeff Laytonc359cf32007-11-16 22:22:06 +0000996/* extract the host portion of the UNC string */
997static char *
998extract_hostname(const char *unc)
999{
1000 const char *src;
1001 char *dst, *delim;
1002 unsigned int len;
1003
1004 /* skip double chars at beginning of string */
1005 /* BB: check validity of these bytes? */
1006 src = unc + 2;
1007
1008 /* delimiter between hostname and sharename is always '\\' now */
1009 delim = strchr(src, '\\');
1010 if (!delim)
1011 return ERR_PTR(-EINVAL);
1012
1013 len = delim - src;
1014 dst = kmalloc((len + 1), GFP_KERNEL);
1015 if (dst == NULL)
1016 return ERR_PTR(-ENOMEM);
1017
1018 memcpy(dst, src, len);
1019 dst[len] = '\0';
1020
1021 return dst;
1022}
1023
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001024static int get_option_ul(substring_t args[], unsigned long *option)
1025{
1026 int rc;
1027 char *string;
1028
1029 string = match_strdup(args);
1030 if (string == NULL)
1031 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001032 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001033 kfree(string);
1034
1035 return rc;
1036}
1037
Eric W. Biederman3da46562013-02-06 01:37:39 -08001038static int get_option_uid(substring_t args[], kuid_t *result)
1039{
1040 unsigned long value;
1041 kuid_t uid;
1042 int rc;
1043
1044 rc = get_option_ul(args, &value);
1045 if (rc)
1046 return rc;
1047
1048 uid = make_kuid(current_user_ns(), value);
1049 if (!uid_valid(uid))
1050 return -EINVAL;
1051
1052 *result = uid;
1053 return 0;
1054}
1055
1056static int get_option_gid(substring_t args[], kgid_t *result)
1057{
1058 unsigned long value;
1059 kgid_t gid;
1060 int rc;
1061
1062 rc = get_option_ul(args, &value);
1063 if (rc)
1064 return rc;
1065
1066 gid = make_kgid(current_user_ns(), value);
1067 if (!gid_valid(gid))
1068 return -EINVAL;
1069
1070 *result = gid;
1071 return 0;
1072}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001073
1074static int cifs_parse_security_flavors(char *value,
1075 struct smb_vol *vol)
1076{
1077
1078 substring_t args[MAX_OPT_ARGS];
1079
Jeff Layton1e3cc572013-06-10 17:12:23 -05001080 /*
1081 * With mount options, the last one should win. Reset any existing
1082 * settings back to default.
1083 */
1084 vol->sectype = Unspecified;
1085 vol->sign = false;
1086
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001087 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001088 case Opt_sec_krb5p:
1089 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1090 return 1;
1091 case Opt_sec_krb5i:
1092 vol->sign = true;
1093 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001094 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001095 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001096 break;
1097 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001098 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001099 /* Fallthrough */
1100 case Opt_sec_ntlmssp:
1101 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001102 break;
1103 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001104 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001105 /* Fallthrough */
1106 case Opt_ntlm:
1107 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001108 break;
1109 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001110 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001111 /* Fallthrough */
1112 case Opt_sec_ntlmv2:
1113 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001114 break;
1115#ifdef CONFIG_CIFS_WEAK_PW_HASH
1116 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001117 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001118 break;
1119#endif
1120 case Opt_sec_none:
1121 vol->nullauth = 1;
1122 break;
1123 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001124 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001125 return 1;
1126 }
1127
1128 return 0;
1129}
1130
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001132cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1133{
1134 substring_t args[MAX_OPT_ARGS];
1135
1136 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1137 case Opt_cache_loose:
1138 vol->direct_io = false;
1139 vol->strict_io = false;
1140 break;
1141 case Opt_cache_strict:
1142 vol->direct_io = false;
1143 vol->strict_io = true;
1144 break;
1145 case Opt_cache_none:
1146 vol->direct_io = true;
1147 vol->strict_io = false;
1148 break;
1149 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001150 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001151 return 1;
1152 }
1153 return 0;
1154}
1155
1156static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001157cifs_parse_smb_version(char *value, struct smb_vol *vol)
1158{
1159 substring_t args[MAX_OPT_ARGS];
1160
1161 switch (match_token(value, cifs_smb_version_tokens, args)) {
1162 case Smb_1:
1163 vol->ops = &smb1_operations;
1164 vol->vals = &smb1_values;
1165 break;
Steve French1080ef72011-02-24 18:07:19 +00001166#ifdef CONFIG_CIFS_SMB2
Steve Frenchdd446b12012-11-28 23:21:06 -06001167 case Smb_20:
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001168 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001169 vol->vals = &smb20_values;
1170 break;
Steve French1080ef72011-02-24 18:07:19 +00001171 case Smb_21:
1172 vol->ops = &smb21_operations;
1173 vol->vals = &smb21_values;
1174 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001175 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001176 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001177 vol->vals = &smb30_values;
1178 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001179 case Smb_302:
1180 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1181 vol->vals = &smb302_values;
1182 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001183#ifdef CONFIG_CIFS_SMB311
1184 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001185 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001186 vol->vals = &smb311_values;
1187 break;
1188#endif /* SMB311 */
Steve French1080ef72011-02-24 18:07:19 +00001189#endif
Jeff Layton23db65f2012-05-15 12:20:51 -04001190 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001191 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001192 return 1;
1193 }
1194 return 0;
1195}
1196
Jeff Laytond387a5c2012-12-10 06:10:46 -05001197/*
1198 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1199 * fields with the result. Returns 0 on success and an error otherwise.
1200 */
1201static int
1202cifs_parse_devname(const char *devname, struct smb_vol *vol)
1203{
1204 char *pos;
1205 const char *delims = "/\\";
1206 size_t len;
1207
Yao Liu9d5a48f2019-01-28 19:47:28 +08001208 if (unlikely(!devname || !*devname)) {
1209 cifs_dbg(VFS, "Device name not specified.\n");
1210 return -EINVAL;
1211 }
1212
Jeff Laytond387a5c2012-12-10 06:10:46 -05001213 /* make sure we have a valid UNC double delimiter prefix */
1214 len = strspn(devname, delims);
1215 if (len != 2)
1216 return -EINVAL;
1217
1218 /* find delimiter between host and sharename */
1219 pos = strpbrk(devname + 2, delims);
1220 if (!pos)
1221 return -EINVAL;
1222
1223 /* skip past delimiter */
1224 ++pos;
1225
1226 /* now go until next delimiter or end of string */
1227 len = strcspn(pos, delims);
1228
1229 /* move "pos" up to delimiter or NULL */
1230 pos += len;
1231 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1232 if (!vol->UNC)
1233 return -ENOMEM;
1234
1235 convert_delimiter(vol->UNC, '\\');
1236
Sachin Prabhu11e31642016-02-08 13:44:01 +05301237 /* skip any delimiter */
1238 if (*pos == '/' || *pos == '\\')
1239 pos++;
1240
1241 /* If pos is NULL then no prepath */
1242 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001243 return 0;
1244
1245 vol->prepath = kstrdup(pos, GFP_KERNEL);
1246 if (!vol->prepath)
1247 return -ENOMEM;
1248
1249 return 0;
1250}
1251
Jeff Layton23db65f2012-05-15 12:20:51 -04001252static int
Sean Finneyb9468452011-04-11 13:19:32 +00001253cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001254 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001256 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001257 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 unsigned int temp_len, i, j;
1259 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001260 short int override_uid = -1;
1261 short int override_gid = -1;
1262 bool uid_specified = false;
1263 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001264 bool sloppy = false;
1265 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001266 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001267 char *string = NULL;
1268 char *tmp_end, *value;
1269 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001270 bool got_ip = false;
1271 unsigned short port = 0;
1272 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001275 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001276 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Jeff Layton6ee95422012-11-26 11:09:57 -05001278 /* ensure we always start with zeroed-out smb_vol */
1279 memset(vol, 0, sizeof(*vol));
1280
Jeff Layton88463992010-11-22 15:31:03 -05001281 /*
1282 * does not have to be perfect mapping since field is
1283 * informational, only used for servers that do not support
1284 * port 445 and it can be overridden at mount time
1285 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001286 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1287 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001288 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1289
Jeff Layton1397f2e2011-01-07 11:30:28 -05001290 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001291 /* null target name indicates to use *SMBSERVR default called name
1292 if we end up sending RFC1001 session initialize */
1293 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001294 vol->cred_uid = current_uid();
1295 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001296 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001297
Steve French2baa2682014-09-27 02:19:01 -05001298 /*
1299 * default to SFM style remapping of seven reserved characters
1300 * unless user overrides it or we negotiate CIFS POSIX where
1301 * it is unnecessary. Can not simultaneously use more than one mapping
1302 * since then readdir could list files that open could not open
1303 */
1304 vol->remap = true;
1305
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001306 /* default to only allowing write access to owner of the mount */
1307 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
1309 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001310 /* default is always to request posix paths. */
1311 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001312 /* default to using server inode numbers where available */
1313 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001314
Jeff Layton1b359202012-09-19 15:20:27 -07001315 /* default is to use strict cifs caching semantics */
1316 vol->strict_io = true;
1317
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301318 vol->actimeo = CIFS_DEF_ACTIMEO;
1319
Jeff Layton23db65f2012-05-15 12:20:51 -04001320 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1321 vol->ops = &smb1_operations;
1322 vol->vals = &smb1_values;
1323
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001324 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1325
Sean Finneyb9468452011-04-11 13:19:32 +00001326 if (!mountdata)
1327 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
Sean Finneyb9468452011-04-11 13:19:32 +00001329 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1330 if (!mountdata_copy)
1331 goto cifs_parse_mount_err;
1332
1333 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001334 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001335
Steve French50c2f752007-07-13 00:33:32 +00001336 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001337 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 separator[0] = options[4];
1339 options += 5;
1340 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001341 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 }
1343 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001344 vol->backupuid_specified = false; /* no backup intent for a user */
1345 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001346
Jeff Layton37d4f992013-05-24 07:40:05 -04001347 switch (cifs_parse_devname(devname, vol)) {
1348 case 0:
1349 break;
1350 case -ENOMEM:
1351 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1352 goto cifs_parse_mount_err;
1353 case -EINVAL:
1354 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1355 goto cifs_parse_mount_err;
1356 default:
1357 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1358 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001359 }
1360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001362 substring_t args[MAX_OPT_ARGS];
1363 unsigned long option;
1364 int token;
1365
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 if (!*data)
1367 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001369 token = match_token(data, cifs_mount_option_tokens, args);
1370
1371 switch (token) {
1372
1373 /* Ingnore the following */
1374 case Opt_ignore:
1375 break;
1376
1377 /* Boolean values */
1378 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001380 break;
1381 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 break;
1384 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001385 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001386 break;
1387 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001388 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001389 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001390 case Opt_forcegid:
1391 override_gid = 1;
1392 break;
1393 case Opt_noforcegid:
1394 override_gid = 0;
1395 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001396 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001397 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001398 break;
1399 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001400 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001401 break;
1402 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001404 break;
1405 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001407 break;
1408 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001410 break;
1411 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001413 break;
1414 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001415 vol->sfu_remap = true;
1416 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001417 break;
1418 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001419 vol->sfu_remap = false;
1420 break;
1421 case Opt_mapposix:
1422 vol->remap = true;
1423 vol->sfu_remap = false; /* disable SFU mapping */
1424 break;
1425 case Opt_nomapposix:
1426 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001427 break;
1428 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001429 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001430 break;
1431 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001432 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001433 break;
1434 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001435 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001436 break;
1437 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001438 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001439 break;
1440 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001441 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001442 break;
1443 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001444 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001445 break;
1446 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001447 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001448 break;
1449 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001450 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001451 break;
1452 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001453 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001454 /*
1455 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001456 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001457 * local vfs will do advisory
1458 */
Steve French50c2f752007-07-13 00:33:32 +00001459 if (vol->file_mode ==
1460 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001461 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001462 break;
1463 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001464 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001465 break;
1466 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001468 break;
1469 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001471 break;
Steve French95932652016-09-23 01:36:34 -05001472 case Opt_setuidfromacl:
1473 vol->setuidfromacl = 1;
1474 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001475 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001476 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001477 break;
1478 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001479 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001480 break;
1481 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001483 break;
1484 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001486 break;
1487 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001489 break;
1490 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001492 break;
1493 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001494 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001495 break;
1496 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001497 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001498 break;
1499 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001501 break;
1502 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001504 break;
1505 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001506 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001507 break;
1508 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001509 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001510 break;
1511 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001512 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001513 break;
1514 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001516 break;
1517 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001519 break;
1520 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001521 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001522 break;
1523 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001524 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001525 break;
1526 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001527 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001528 * is a per tree connection (mount) not a per socket
1529 * or per-smb connection option in the protocol
1530 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1531 */
Steve French95b1cb92008-05-15 16:44:38 +00001532 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001533 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001534 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001535 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001536 break;
1537 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301538#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001539 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001540 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301541#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301542 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001543 break;
1544 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001545 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001546 break;
1547 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001548 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001549 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001550 case Opt_sloppy:
1551 sloppy = true;
1552 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001553 case Opt_nosharesock:
1554 vol->nosharesock = true;
1555 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001556 case Opt_nopersistent:
1557 vol->nopersistent = true;
1558 if (vol->persistent) {
1559 cifs_dbg(VFS,
1560 "persistenthandles mount options conflict\n");
1561 goto cifs_parse_mount_err;
1562 }
1563 break;
1564 case Opt_persistent:
1565 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001566 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001567 cifs_dbg(VFS,
1568 "persistenthandles mount options conflict\n");
1569 goto cifs_parse_mount_err;
1570 }
1571 break;
Steve French592fafe2015-11-03 10:08:53 -06001572 case Opt_resilient:
1573 vol->resilient = true;
1574 if (vol->persistent) {
1575 cifs_dbg(VFS,
1576 "persistenthandles mount options conflict\n");
1577 goto cifs_parse_mount_err;
1578 }
1579 break;
1580 case Opt_noresilient:
1581 vol->resilient = false; /* already the default */
1582 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001583
1584 /* Numeric Values */
1585 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001586 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001587 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1588 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001589 goto cifs_parse_mount_err;
1590 }
1591 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001592 break;
1593 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001594 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001595 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1596 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001597 goto cifs_parse_mount_err;
1598 }
1599 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001600 break;
1601 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001602 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001603 cifs_dbg(VFS, "%s: Invalid uid value\n",
1604 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001605 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001607 uid_specified = true;
1608 break;
1609 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001610 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001611 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1612 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001613 goto cifs_parse_mount_err;
1614 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001615 break;
1616 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001617 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001618 cifs_dbg(VFS, "%s: Invalid gid value\n",
1619 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001620 goto cifs_parse_mount_err;
1621 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001622 gid_specified = true;
1623 break;
1624 case Opt_file_mode:
1625 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001626 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1627 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001628 goto cifs_parse_mount_err;
1629 }
1630 vol->file_mode = option;
1631 break;
1632 case Opt_dirmode:
1633 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001634 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1635 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001636 goto cifs_parse_mount_err;
1637 }
1638 vol->dir_mode = option;
1639 break;
1640 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001641 if (get_option_ul(args, &option) ||
1642 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001643 cifs_dbg(VFS, "%s: Invalid port value\n",
1644 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001645 goto cifs_parse_mount_err;
1646 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001647 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001648 break;
1649 case Opt_rsize:
1650 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001651 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1652 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001653 goto cifs_parse_mount_err;
1654 }
1655 vol->rsize = option;
1656 break;
1657 case Opt_wsize:
1658 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001659 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1660 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001661 goto cifs_parse_mount_err;
1662 }
1663 vol->wsize = option;
1664 break;
1665 case Opt_actimeo:
1666 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001667 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1668 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001669 goto cifs_parse_mount_err;
1670 }
1671 vol->actimeo = HZ * option;
1672 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001673 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001674 goto cifs_parse_mount_err;
1675 }
1676 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06001677 case Opt_echo_interval:
1678 if (get_option_ul(args, &option)) {
1679 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
1680 __func__);
1681 goto cifs_parse_mount_err;
1682 }
1683 vol->echo_interval = option;
1684 break;
Steve French141891f2016-09-23 00:44:16 -05001685 case Opt_max_credits:
1686 if (get_option_ul(args, &option) || (option < 20) ||
1687 (option > 60000)) {
1688 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1689 __func__);
1690 goto cifs_parse_mount_err;
1691 }
1692 vol->max_credits = option;
1693 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001694
1695 /* String Arguments */
1696
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001697 case Opt_blank_user:
1698 /* null user, ie. anonymous authentication */
1699 vol->nullauth = 1;
1700 vol->username = NULL;
1701 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001702 case Opt_user:
1703 string = match_strdup(args);
1704 if (string == NULL)
1705 goto out_nomem;
1706
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001707 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1708 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001709 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001710 goto cifs_parse_mount_err;
1711 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001712
1713 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001714 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001715 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001716 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001717 break;
1718 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001719 /* passwords have to be handled differently
1720 * to allow the character used for deliminator
1721 * to be passed within them
1722 */
1723
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001724 /*
1725 * Check if this is a case where the password
1726 * starts with a delimiter
1727 */
1728 tmp_end = strchr(data, '=');
1729 tmp_end++;
1730 if (!(tmp_end < end && tmp_end[1] == delim)) {
1731 /* No it is not. Set the password to NULL */
Aurelien Aptel7e689162018-01-25 15:59:39 +01001732 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001733 vol->password = NULL;
1734 break;
1735 }
1736 /* Yes it is. Drop down to Opt_pass below.*/
1737 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001738 /* Obtain the value string */
1739 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001740 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001741
1742 /* Set tmp_end to end of the string */
1743 tmp_end = (char *) value + strlen(value);
1744
1745 /* Check if following character is the deliminator
1746 * If yes, we have encountered a double deliminator
1747 * reset the NULL character to the deliminator
1748 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301749 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001750 tmp_end[0] = delim;
1751
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301752 /* Keep iterating until we get to a single
1753 * deliminator OR the end
1754 */
1755 while ((tmp_end = strchr(tmp_end, delim))
1756 != NULL && (tmp_end[1] == delim)) {
1757 tmp_end = (char *) &tmp_end[2];
1758 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001759
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301760 /* Reset var options to point to next element */
1761 if (tmp_end) {
1762 tmp_end[0] = '\0';
1763 options = (char *) &tmp_end[1];
1764 } else
1765 /* Reached the end of the mount option
1766 * string */
1767 options = end;
1768 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001769
Aurelien Aptel7e689162018-01-25 15:59:39 +01001770 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001771 /* Now build new password string */
1772 temp_len = strlen(value);
1773 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1774 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001775 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001776 goto cifs_parse_mount_err;
1777 }
1778
1779 for (i = 0, j = 0; i < temp_len; i++, j++) {
1780 vol->password[j] = value[i];
1781 if ((value[i] == delim) &&
1782 value[i+1] == delim)
1783 /* skip the second deliminator */
1784 i++;
1785 }
1786 vol->password[j] = '\0';
1787 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001788 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001789 /* FIXME: should this be an error instead? */
1790 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001791 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001792 case Opt_ip:
1793 string = match_strdup(args);
1794 if (string == NULL)
1795 goto out_nomem;
1796
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001797 if (!cifs_convert_address(dstaddr, string,
1798 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001799 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001800 goto cifs_parse_mount_err;
1801 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001802 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001804 case Opt_domain:
1805 string = match_strdup(args);
1806 if (string == NULL)
1807 goto out_nomem;
1808
Chen Gang057d6332013-07-19 09:01:36 +08001809 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
1810 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001811 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001812 goto cifs_parse_mount_err;
1813 }
1814
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001815 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001816 vol->domainname = kstrdup(string, GFP_KERNEL);
1817 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001818 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001819 goto cifs_parse_mount_err;
1820 }
Joe Perchesf96637b2013-05-04 22:12:25 -05001821 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001822 break;
1823 case Opt_srcaddr:
1824 string = match_strdup(args);
1825 if (string == NULL)
1826 goto out_nomem;
1827
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001828 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001829 (struct sockaddr *)&vol->srcaddr,
1830 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001831 pr_warn("CIFS: Could not parse srcaddr: %s\n",
1832 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001833 goto cifs_parse_mount_err;
1834 }
1835 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001836 case Opt_iocharset:
1837 string = match_strdup(args);
1838 if (string == NULL)
1839 goto out_nomem;
1840
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001841 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001842 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001843 goto cifs_parse_mount_err;
1844 }
1845
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001846 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001847 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001848 vol->iocharset = kstrdup(string,
1849 GFP_KERNEL);
1850 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001851 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001852 goto cifs_parse_mount_err;
1853 }
1854 }
1855 /* if iocharset not set then load_nls_default
1856 * is used by caller
1857 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001858 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001859 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001860 case Opt_netbiosname:
1861 string = match_strdup(args);
1862 if (string == NULL)
1863 goto out_nomem;
1864
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001865 memset(vol->source_rfc1001_name, 0x20,
1866 RFC1001_NAME_LEN);
1867 /*
1868 * FIXME: are there cases in which a comma can
1869 * be valid in workstation netbios name (and
1870 * need special handling)?
1871 */
1872 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1873 /* don't ucase netbiosname for user */
1874 if (string[i] == 0)
1875 break;
1876 vol->source_rfc1001_name[i] = string[i];
1877 }
1878 /* The string has 16th byte zero still from
1879 * set at top of the function
1880 */
1881 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001882 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001883 break;
1884 case Opt_servern:
1885 /* servernetbiosname specified override *SMBSERVER */
1886 string = match_strdup(args);
1887 if (string == NULL)
1888 goto out_nomem;
1889
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001890 /* last byte, type, is 0x20 for servr type */
1891 memset(vol->target_rfc1001_name, 0x20,
1892 RFC1001_NAME_LEN_WITH_NULL);
1893
1894 /* BB are there cases in which a comma can be
1895 valid in this workstation netbios name
1896 (and need special handling)? */
1897
1898 /* user or mount helper must uppercase the
1899 netbios name */
1900 for (i = 0; i < 15; i++) {
1901 if (string[i] == 0)
1902 break;
1903 vol->target_rfc1001_name[i] = string[i];
1904 }
1905 /* The string has 16th byte zero still from
1906 set at top of the function */
1907 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001908 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001909 break;
1910 case Opt_ver:
1911 string = match_strdup(args);
1912 if (string == NULL)
1913 goto out_nomem;
1914
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001915 if (strncasecmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001916 /* This is the default */
1917 break;
1918 }
1919 /* For all other value, error */
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001920 pr_warn("CIFS: Invalid version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001921 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001922 case Opt_vers:
1923 string = match_strdup(args);
1924 if (string == NULL)
1925 goto out_nomem;
1926
1927 if (cifs_parse_smb_version(string, vol) != 0)
1928 goto cifs_parse_mount_err;
1929 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001930 case Opt_sec:
1931 string = match_strdup(args);
1932 if (string == NULL)
1933 goto out_nomem;
1934
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001935 if (cifs_parse_security_flavors(string, vol) != 0)
1936 goto cifs_parse_mount_err;
1937 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001938 case Opt_cache:
1939 string = match_strdup(args);
1940 if (string == NULL)
1941 goto out_nomem;
1942
1943 if (cifs_parse_cache_flavor(string, vol) != 0)
1944 goto cifs_parse_mount_err;
1945 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001946 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001947 /*
1948 * An option we don't recognize. Save it off for later
1949 * if we haven't already found one
1950 */
1951 if (!invalid)
1952 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001953 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001955 /* Free up any allocated string */
1956 kfree(string);
1957 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001959
Jeff Laytond8162552012-03-23 14:40:56 -04001960 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001961 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04001962 goto cifs_parse_mount_err;
1963 }
1964
Jeff Layton8a8798a2012-01-17 16:09:15 -05001965#ifndef CONFIG_KEYS
1966 /* Muliuser mounts require CONFIG_KEYS support */
1967 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001968 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001969 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001970 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001971#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001972 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04001973 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001974 goto cifs_parse_mount_err;
1975 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001976
Jeff Layton62a1a432012-12-10 06:10:45 -05001977 /* make sure UNC has a share name */
1978 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001979 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05001980 goto cifs_parse_mount_err;
1981 }
1982
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001983 if (!got_ip) {
1984 /* No ip= option specified? Try to get it from UNC */
1985 if (!cifs_convert_address(dstaddr, &vol->UNC[2],
1986 strlen(&vol->UNC[2]))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001987 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001988 goto cifs_parse_mount_err;
1989 }
1990 }
1991
1992 /* set the port that we got earlier */
1993 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001995 if (uid_specified)
1996 vol->override_uid = override_uid;
1997 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001998 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001999
2000 if (gid_specified)
2001 vol->override_gid = override_gid;
2002 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002003 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002004
Sean Finneyb9468452011-04-11 13:19:32 +00002005 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002007
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002008out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002009 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002010cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002011 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002012 kfree(mountdata_copy);
2013 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014}
2015
Ben Greear3eb9a882010-09-01 17:06:02 -07002016/** Returns true if srcaddr isn't specified and rhs isn't
2017 * specified, or if srcaddr is specified and
2018 * matches the IP address of the rhs argument.
2019 */
Jeff Layton45151482010-07-06 20:43:02 -04002020static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002021srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2022{
2023 switch (srcaddr->sa_family) {
2024 case AF_UNSPEC:
2025 return (rhs->sa_family == AF_UNSPEC);
2026 case AF_INET: {
2027 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2028 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2029 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2030 }
2031 case AF_INET6: {
2032 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002033 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002034 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2035 }
2036 default:
2037 WARN_ON(1);
2038 return false; /* don't expect to be here */
2039 }
2040}
2041
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002042/*
2043 * If no port is specified in addr structure, we try to match with 445 port
2044 * and if it fails - with 139 ports. It should be called only if address
2045 * families of server and addr are equal.
2046 */
2047static bool
2048match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2049{
Steve French6da97912011-03-13 18:55:55 +00002050 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002051
2052 switch (addr->sa_family) {
2053 case AF_INET:
2054 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2055 port = ((struct sockaddr_in *) addr)->sin_port;
2056 break;
2057 case AF_INET6:
2058 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2059 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2060 break;
2061 default:
2062 WARN_ON(1);
2063 return false;
2064 }
2065
2066 if (!port) {
2067 port = htons(CIFS_PORT);
2068 if (port == *sport)
2069 return true;
2070
2071 port = htons(RFC1001_PORT);
2072 }
2073
2074 return port == *sport;
2075}
Ben Greear3eb9a882010-09-01 17:06:02 -07002076
2077static bool
2078match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2079 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080{
Jeff Layton45151482010-07-06 20:43:02 -04002081 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002082 case AF_INET: {
2083 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2084 struct sockaddr_in *srv_addr4 =
2085 (struct sockaddr_in *)&server->dstaddr;
2086
2087 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002088 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002089 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002090 }
2091 case AF_INET6: {
2092 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2093 struct sockaddr_in6 *srv_addr6 =
2094 (struct sockaddr_in6 *)&server->dstaddr;
2095
Jeff Layton45151482010-07-06 20:43:02 -04002096 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002097 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002098 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002099 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002100 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002101 break;
2102 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002103 default:
2104 WARN_ON(1);
2105 return false; /* don't expect to be here */
2106 }
Jeff Layton45151482010-07-06 20:43:02 -04002107
Ben Greear3eb9a882010-09-01 17:06:02 -07002108 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2109 return false;
2110
Jeff Layton45151482010-07-06 20:43:02 -04002111 return true;
2112}
2113
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002114static bool
2115match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2116{
Jeff Layton3f618222013-06-12 19:52:14 -05002117 /*
2118 * The select_sectype function should either return the vol->sectype
2119 * that was specified, or "Unspecified" if that sectype was not
2120 * compatible with the given NEGOTIATE request.
2121 */
2122 if (select_sectype(server, vol->sectype) == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002123 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002124
Jeff Layton3f618222013-06-12 19:52:14 -05002125 /*
2126 * Now check if signing mode is acceptable. No need to check
2127 * global_secflags at this point since if MUST_SIGN is set then
2128 * the server->sign had better be too.
2129 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002130 if (vol->sign && !server->sign)
2131 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002132
2133 return true;
2134}
2135
Jeff Layton9fa114f2012-11-26 11:09:57 -05002136static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002137{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002138 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2139
Jeff Laytona0b3df52013-05-24 07:40:59 -04002140 if (vol->nosharesock)
2141 return 0;
2142
Jeff Layton23db65f2012-05-15 12:20:51 -04002143 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2144 return 0;
2145
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002146 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2147 return 0;
2148
2149 if (!match_address(server, addr,
2150 (struct sockaddr *)&vol->srcaddr))
2151 return 0;
2152
2153 if (!match_port(server, addr))
2154 return 0;
2155
2156 if (!match_security(server, vol))
2157 return 0;
2158
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002159 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002160 return 0;
2161
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002162 return 1;
2163}
2164
Jeff Layton45151482010-07-06 20:43:02 -04002165static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002166cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002167{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002168 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302170 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002171 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002172 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002173 continue;
2174
Jeff Laytone7ddee92008-11-14 13:44:38 -05002175 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302176 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002177 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002178 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302180 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 return NULL;
2182}
2183
Pavel Shilovsky48f95262016-11-04 11:50:31 -07002184void
2185cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002187 struct task_struct *task;
2188
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302189 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002190 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302191 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002192 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002194
Rob Landleyf1d0c992011-01-22 15:44:05 -06002195 put_net(cifs_net_ns(server));
2196
Jeff Laytone7ddee92008-11-14 13:44:38 -05002197 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302198 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002199
Jeff Laytonc74093b2011-01-11 07:24:23 -05002200 cancel_delayed_work_sync(&server->echo);
2201
Pavel Shilovsky48f95262016-11-04 11:50:31 -07002202#ifdef CONFIG_CIFS_SMB2
2203 if (from_reconnect)
2204 /*
2205 * Avoid deadlock here: reconnect work calls
2206 * cifs_put_tcp_session() at its end. Need to be sure
2207 * that reconnect work does nothing with server pointer after
2208 * that step.
2209 */
2210 cancel_delayed_work(&server->reconnect);
2211 else
2212 cancel_delayed_work_sync(&server->reconnect);
2213#endif
2214
Jeff Laytone7ddee92008-11-14 13:44:38 -05002215 spin_lock(&GlobalMid_Lock);
2216 server->tcpStatus = CifsExiting;
2217 spin_unlock(&GlobalMid_Lock);
2218
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002219 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302220 cifs_fscache_release_client_cookie(server);
2221
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002222 kfree(server->session_key.response);
2223 server->session_key.response = NULL;
2224 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002225
2226 task = xchg(&server->tsk, NULL);
2227 if (task)
Eric W. Biedermane038a1b62019-05-15 12:33:50 -05002228 send_sig(SIGKILL, task, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229}
2230
Jeff Layton63c038c2008-12-01 18:41:46 -05002231static struct TCP_Server_Info *
2232cifs_get_tcp_session(struct smb_vol *volume_info)
2233{
2234 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002235 int rc;
2236
Joe Perchesf96637b2013-05-04 22:12:25 -05002237 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002238
2239 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002240 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002241 if (tcp_ses)
2242 return tcp_ses;
2243
2244 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2245 if (!tcp_ses) {
2246 rc = -ENOMEM;
2247 goto out_err;
2248 }
2249
Jeff Layton23db65f2012-05-15 12:20:51 -04002250 tcp_ses->ops = volume_info->ops;
2251 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002252 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002253 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2254 if (IS_ERR(tcp_ses->hostname)) {
2255 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002256 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002257 }
2258
2259 tcp_ses->noblocksnd = volume_info->noblocksnd;
2260 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002261 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002262 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002263 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002264 init_waitqueue_head(&tcp_ses->response_q);
2265 init_waitqueue_head(&tcp_ses->request_q);
2266 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2267 mutex_init(&tcp_ses->srv_mutex);
2268 memcpy(tcp_ses->workstation_RFC1001_name,
2269 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2270 memcpy(tcp_ses->server_RFC1001_name,
2271 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002272 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002273 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002274 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002275 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002276 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2277 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002278 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky48f95262016-11-04 11:50:31 -07002279#ifdef CONFIG_CIFS_SMB2
2280 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2281 mutex_init(&tcp_ses->reconnect_mutex);
2282#endif
Jeff Layton9fa114f2012-11-26 11:09:57 -05002283 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2284 sizeof(tcp_ses->srcaddr));
2285 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2286 sizeof(tcp_ses->dstaddr));
Sachin Prabhu39552ea2014-05-13 00:48:12 +01002287#ifdef CONFIG_CIFS_SMB2
Steve Frenchfa70b872016-09-22 00:39:34 -05002288 generate_random_uuid(tcp_ses->client_guid);
Sachin Prabhu39552ea2014-05-13 00:48:12 +01002289#endif
Jeff Layton63c038c2008-12-01 18:41:46 -05002290 /*
2291 * at this point we are the only ones with the pointer
2292 * to the struct since the kernel thread not created yet
2293 * no need to spinlock this init of tcpStatus or srv_count
2294 */
2295 tcp_ses->tcpStatus = CifsNew;
2296 ++tcp_ses->srv_count;
2297
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002298 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2299 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2300 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2301 else
2302 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
2303
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002304 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002305 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002306 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002307 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002308 }
2309
2310 /*
2311 * since we're in a cifs function already, we know that
2312 * this will succeed. No need for try_module_get().
2313 */
2314 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002315 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002316 tcp_ses, "cifsd");
2317 if (IS_ERR(tcp_ses->tsk)) {
2318 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002319 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002320 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002321 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002322 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002323 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002324
2325 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302326 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002327 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302328 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002329
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302330 cifs_fscache_get_client_cookie(tcp_ses);
2331
Jeff Laytonc74093b2011-01-11 07:24:23 -05002332 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002333 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002334
Jeff Layton63c038c2008-12-01 18:41:46 -05002335 return tcp_ses;
2336
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002337out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002338 cifs_crypto_shash_release(tcp_ses);
2339
Rob Landleyf1d0c992011-01-22 15:44:05 -06002340 put_net(cifs_net_ns(tcp_ses));
2341
Jeff Layton63c038c2008-12-01 18:41:46 -05002342out_err:
2343 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002344 if (!IS_ERR(tcp_ses->hostname))
2345 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002346 if (tcp_ses->ssocket)
2347 sock_release(tcp_ses->ssocket);
2348 kfree(tcp_ses);
2349 }
2350 return ERR_PTR(rc);
2351}
2352
Steve French96daf2b2011-05-27 04:34:02 +00002353static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002354{
Jeff Layton3f618222013-06-12 19:52:14 -05002355 if (vol->sectype != Unspecified &&
2356 vol->sectype != ses->sectype)
2357 return 0;
2358
2359 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002360 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002361 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002362 return 0;
2363 break;
2364 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002365 /* NULL username means anonymous session */
2366 if (ses->user_name == NULL) {
2367 if (!vol->nullauth)
2368 return 0;
2369 break;
2370 }
2371
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002372 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002373 if (strncmp(ses->user_name,
2374 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002375 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002376 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002377 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002378 ses->password != NULL &&
2379 strncmp(ses->password,
2380 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002381 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002382 return 0;
2383 }
2384 return 1;
2385}
2386
Steve French96daf2b2011-05-27 04:34:02 +00002387static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002388cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389{
Steve French96daf2b2011-05-27 04:34:02 +00002390 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302392 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002393 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002394 if (ses->status == CifsExiting)
2395 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002396 if (!match_session(ses, vol))
2397 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002398 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302399 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002400 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302402 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 return NULL;
2404}
2405
Jeff Layton14fbf502008-11-14 13:53:46 -05002406static void
Steve French96daf2b2011-05-27 04:34:02 +00002407cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002408{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002409 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002410 struct TCP_Server_Info *server = ses->server;
2411
Joe Perchesf96637b2013-05-04 22:12:25 -05002412 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002413
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302414 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002415 if (ses->status == CifsExiting) {
2416 spin_unlock(&cifs_tcp_ses_lock);
2417 return;
2418 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002419 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302420 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002421 return;
2422 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002423 if (ses->status == CifsGood)
2424 ses->status = CifsExiting;
2425 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002426
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002427 if (ses->status == CifsExiting && server->ops->logoff) {
2428 xid = get_xid();
2429 rc = server->ops->logoff(xid, ses);
2430 if (rc)
2431 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2432 __func__, rc);
2433 _free_xid(xid);
2434 }
2435
2436 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002437 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302438 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002439
Jeff Layton14fbf502008-11-14 13:53:46 -05002440 sesInfoFree(ses);
Pavel Shilovsky48f95262016-11-04 11:50:31 -07002441 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05002442}
2443
Jeff Layton8a8798a2012-01-17 16:09:15 -05002444#ifdef CONFIG_KEYS
2445
Chen Gang057d6332013-07-19 09:01:36 +08002446/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2447#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002448
2449/* Populate username and pw fields from keyring if possible */
2450static int
2451cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2452{
2453 int rc = 0;
Ronnie Sahlberg16764d72019-08-22 08:09:50 +10002454 int is_domain = 0;
David Howells146aa8b2015-10-21 14:04:48 +01002455 const char *delim, *payload;
2456 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002457 ssize_t len;
2458 struct key *key;
2459 struct TCP_Server_Info *server = ses->server;
2460 struct sockaddr_in *sa;
2461 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01002462 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002463
2464 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2465 if (!desc)
2466 return -ENOMEM;
2467
2468 /* try to find an address key first */
2469 switch (server->dstaddr.ss_family) {
2470 case AF_INET:
2471 sa = (struct sockaddr_in *)&server->dstaddr;
2472 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2473 break;
2474 case AF_INET6:
2475 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2476 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2477 break;
2478 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002479 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2480 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002481 rc = -EINVAL;
2482 goto out_err;
2483 }
2484
Joe Perchesf96637b2013-05-04 22:12:25 -05002485 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002486 key = request_key(&key_type_logon, desc, "");
2487 if (IS_ERR(key)) {
2488 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002489 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002490 rc = PTR_ERR(key);
2491 goto out_err;
2492 }
2493
2494 /* didn't work, try to find a domain key */
2495 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002496 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002497 key = request_key(&key_type_logon, desc, "");
2498 if (IS_ERR(key)) {
2499 rc = PTR_ERR(key);
2500 goto out_err;
2501 }
Ronnie Sahlberg16764d72019-08-22 08:09:50 +10002502 is_domain = 1;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002503 }
2504
2505 down_read(&key->sem);
Hyojun Kim63da4202017-10-06 17:10:08 -07002506 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002507 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002508 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002509 goto out_key_put;
2510 }
2511
2512 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01002513 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002514 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002515 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002516 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002517 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2518 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002519 rc = -EINVAL;
2520 goto out_key_put;
2521 }
2522
2523 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002524 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002525 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2526 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002527 rc = -EINVAL;
2528 goto out_key_put;
2529 }
2530
2531 vol->username = kstrndup(payload, len, GFP_KERNEL);
2532 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002533 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2534 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002535 rc = -ENOMEM;
2536 goto out_key_put;
2537 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002538 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002539
2540 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002541 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002542 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002543 rc = -EINVAL;
2544 kfree(vol->username);
2545 vol->username = NULL;
2546 goto out_key_put;
2547 }
2548
2549 ++delim;
2550 vol->password = kstrndup(delim, len, GFP_KERNEL);
2551 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002552 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2553 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002554 rc = -ENOMEM;
2555 kfree(vol->username);
2556 vol->username = NULL;
2557 goto out_key_put;
2558 }
2559
Ronnie Sahlberg16764d72019-08-22 08:09:50 +10002560 /*
2561 * If we have a domain key then we must set the domainName in the
2562 * for the request.
2563 */
2564 if (is_domain && ses->domainName) {
2565 vol->domainname = kstrndup(ses->domainName,
2566 strlen(ses->domainName),
2567 GFP_KERNEL);
2568 if (!vol->domainname) {
2569 cifs_dbg(FYI, "Unable to allocate %zd bytes for "
2570 "domain\n", len);
2571 rc = -ENOMEM;
2572 kfree(vol->username);
2573 vol->username = NULL;
Dan Carpenter3571c9b2019-08-27 13:59:17 +03002574 kzfree(vol->password);
Ronnie Sahlberg16764d72019-08-22 08:09:50 +10002575 vol->password = NULL;
2576 goto out_key_put;
2577 }
2578 }
2579
Jeff Layton8a8798a2012-01-17 16:09:15 -05002580out_key_put:
2581 up_read(&key->sem);
2582 key_put(key);
2583out_err:
2584 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002585 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002586 return rc;
2587}
2588#else /* ! CONFIG_KEYS */
2589static inline int
2590cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2591 struct cifs_ses *ses __attribute__((unused)))
2592{
2593 return -ENOSYS;
2594}
2595#endif /* CONFIG_KEYS */
2596
Steve French96daf2b2011-05-27 04:34:02 +00002597static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002598cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2599{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002600 int rc = -ENOMEM;
2601 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002602 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002603 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2604 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002605
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002606 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002607
Jeff Layton4ff67b72010-07-06 20:43:02 -04002608 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002609 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002610 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2611 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002612
Jeff Layton36988c72010-04-24 07:57:43 -04002613 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002614 rc = cifs_negotiate_protocol(xid, ses);
2615 if (rc) {
2616 mutex_unlock(&ses->session_mutex);
2617 /* problem -- put our ses reference */
2618 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002619 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002620 return ERR_PTR(rc);
2621 }
Jeff Layton36988c72010-04-24 07:57:43 -04002622 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002623 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002624 rc = cifs_setup_session(xid, ses,
2625 volume_info->local_nls);
2626 if (rc) {
2627 mutex_unlock(&ses->session_mutex);
2628 /* problem -- put our reference */
2629 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002630 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002631 return ERR_PTR(rc);
2632 }
2633 }
2634 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002635
2636 /* existing SMB ses has a server reference already */
Pavel Shilovsky48f95262016-11-04 11:50:31 -07002637 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002638 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002639 return ses;
2640 }
2641
Joe Perchesf96637b2013-05-04 22:12:25 -05002642 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002643 ses = sesInfoAlloc();
2644 if (ses == NULL)
2645 goto get_ses_fail;
2646
2647 /* new SMB session uses our server ref */
2648 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002649 if (server->dstaddr.ss_family == AF_INET6)
2650 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002651 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002652 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002653
Steve French8727c8a2011-02-25 01:11:56 -06002654 if (volume_info->username) {
2655 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2656 if (!ses->user_name)
2657 goto get_ses_fail;
2658 }
Jeff Layton36988c72010-04-24 07:57:43 -04002659
2660 /* volume_info->password freed at unmount */
2661 if (volume_info->password) {
2662 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2663 if (!ses->password)
2664 goto get_ses_fail;
2665 }
2666 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002667 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2668 if (!ses->domainName)
2669 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002670 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002671 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002672 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002673
Jeff Layton28e11bd2013-05-26 07:01:00 -04002674 ses->sectype = volume_info->sectype;
2675 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04002676
2677 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002678 rc = cifs_negotiate_protocol(xid, ses);
2679 if (!rc)
2680 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002681 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002682 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002683 goto get_ses_fail;
2684
2685 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302686 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002687 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302688 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002689
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002690 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002691 return ses;
2692
2693get_ses_fail:
2694 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002695 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002696 return ERR_PTR(rc);
2697}
2698
Steve French96daf2b2011-05-27 04:34:02 +00002699static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002700{
2701 if (tcon->tidStatus == CifsExiting)
2702 return 0;
2703 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2704 return 0;
2705 return 1;
2706}
2707
Steve French96daf2b2011-05-27 04:34:02 +00002708static struct cifs_tcon *
2709cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710{
2711 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002712 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302714 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002715 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002716 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002717 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002718 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002719 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302720 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 return tcon;
2722 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302723 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 return NULL;
2725}
2726
Pavel Shilovsky48f95262016-11-04 11:50:31 -07002727void
Steve French96daf2b2011-05-27 04:34:02 +00002728cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002729{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002730 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002731 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002732
Joe Perchesf96637b2013-05-04 22:12:25 -05002733 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302734 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002735 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302736 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002737 return;
2738 }
2739
2740 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302741 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002742
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002743 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002744 if (ses->server->ops->tree_disconnect)
2745 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002746 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002747
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302748 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002749 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002750 cifs_put_smb_ses(ses);
2751}
2752
Steve French96daf2b2011-05-27 04:34:02 +00002753static struct cifs_tcon *
2754cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002755{
2756 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002757 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002758
2759 tcon = cifs_find_tcon(ses, volume_info->UNC);
2760 if (tcon) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002761 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002762 /* existing tcon already has a reference */
2763 cifs_put_smb_ses(ses);
2764 if (tcon->seal != volume_info->seal)
Joe Perchesf96637b2013-05-04 22:12:25 -05002765 cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002766 return tcon;
2767 }
2768
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002769 if (!ses->server->ops->tree_connect) {
2770 rc = -ENOSYS;
2771 goto out_fail;
2772 }
2773
Jeff Laytond00c28d2010-04-24 07:57:44 -04002774 tcon = tconInfoAlloc();
2775 if (tcon == NULL) {
2776 rc = -ENOMEM;
2777 goto out_fail;
2778 }
2779
2780 tcon->ses = ses;
2781 if (volume_info->password) {
2782 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2783 if (!tcon->password) {
2784 rc = -ENOMEM;
2785 goto out_fail;
2786 }
2787 }
2788
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002789 /*
2790 * BB Do we need to wrap session_mutex around this TCon call and Unix
2791 * SetFS as we do on SessSetup and reconnect?
2792 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002793 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002794 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
2795 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002796 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05002797 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002798 if (rc)
2799 goto out_fail;
2800
2801 if (volume_info->nodfs) {
2802 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002803 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002804 }
2805 tcon->seal = volume_info->seal;
Steve Frenchb618f002015-11-03 09:15:03 -06002806 tcon->use_persistent = false;
2807 /* check if SMB2 or later, CIFS does not support persistent handles */
2808 if (volume_info->persistent) {
2809 if (ses->server->vals->protocol_id == 0) {
2810 cifs_dbg(VFS,
2811 "SMB3 or later required for persistent handles\n");
2812 rc = -EOPNOTSUPP;
2813 goto out_fail;
Steve French592fafe2015-11-03 10:08:53 -06002814#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06002815 } else if (ses->server->capabilities &
2816 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2817 tcon->use_persistent = true;
2818 else /* persistent handles requested but not supported */ {
2819 cifs_dbg(VFS,
2820 "Persistent handles not supported on share\n");
2821 rc = -EOPNOTSUPP;
2822 goto out_fail;
Steve French592fafe2015-11-03 10:08:53 -06002823#endif /* CONFIG_CIFS_SMB2 */
Steve Frenchb618f002015-11-03 09:15:03 -06002824 }
Steve French592fafe2015-11-03 10:08:53 -06002825#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06002826 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
2827 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2828 && (volume_info->nopersistent == false)) {
2829 cifs_dbg(FYI, "enabling persistent handles\n");
2830 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06002831#endif /* CONFIG_CIFS_SMB2 */
2832 } else if (volume_info->resilient) {
2833 if (ses->server->vals->protocol_id == 0) {
2834 cifs_dbg(VFS,
2835 "SMB2.1 or later required for resilient handles\n");
2836 rc = -EOPNOTSUPP;
2837 goto out_fail;
2838 }
2839 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06002840 }
2841
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002842 /*
2843 * We can have only one retry value for a connection to a share so for
2844 * resources mounted more than once to the same server share the last
2845 * value passed in for the retry flag is used.
2846 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04002847 tcon->retry = volume_info->retry;
2848 tcon->nocase = volume_info->nocase;
2849 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07002850 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002851
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302852 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002853 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302854 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002855
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302856 cifs_fscache_get_super_cookie(tcon);
2857
Jeff Laytond00c28d2010-04-24 07:57:44 -04002858 return tcon;
2859
2860out_fail:
2861 tconInfoFree(tcon);
2862 return ERR_PTR(rc);
2863}
2864
Jeff Layton9d002df2010-10-06 19:51:11 -04002865void
2866cifs_put_tlink(struct tcon_link *tlink)
2867{
2868 if (!tlink || IS_ERR(tlink))
2869 return;
2870
2871 if (!atomic_dec_and_test(&tlink->tl_count) ||
2872 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2873 tlink->tl_time = jiffies;
2874 return;
2875 }
2876
2877 if (!IS_ERR(tlink_tcon(tlink)))
2878 cifs_put_tcon(tlink_tcon(tlink));
2879 kfree(tlink);
2880 return;
2881}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002882
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002883static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002884cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2885{
2886 return cifs_sb->master_tlink;
2887}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002888
2889static int
2890compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2891{
2892 struct cifs_sb_info *old = CIFS_SB(sb);
2893 struct cifs_sb_info *new = mnt_data->cifs_sb;
2894
2895 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2896 return 0;
2897
2898 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2899 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2900 return 0;
2901
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002902 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002903 * We want to share sb only if we don't specify an r/wsize or
2904 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002905 */
2906 if (new->wsize && new->wsize < old->wsize)
2907 return 0;
2908
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002909 if (new->rsize && new->rsize < old->rsize)
2910 return 0;
2911
Eric W. Biederman1f682332013-02-06 01:20:20 -08002912 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002913 return 0;
2914
2915 if (old->mnt_file_mode != new->mnt_file_mode ||
2916 old->mnt_dir_mode != new->mnt_dir_mode)
2917 return 0;
2918
2919 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2920 return 0;
2921
2922 if (old->actimeo != new->actimeo)
2923 return 0;
2924
2925 return 1;
2926}
2927
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01002928static int
2929match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2930{
2931 struct cifs_sb_info *old = CIFS_SB(sb);
2932 struct cifs_sb_info *new = mnt_data->cifs_sb;
Ronnie Sahlberg5b327442020-01-22 11:07:56 +10002933 bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
2934 old->prepath;
2935 bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
2936 new->prepath;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01002937
Sachin Prabhu4f5e1c42017-04-26 14:05:46 +01002938 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01002939 return 1;
Sachin Prabhu4f5e1c42017-04-26 14:05:46 +01002940 else if (!old_set && !new_set)
2941 return 1;
2942
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01002943 return 0;
2944}
2945
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002946int
2947cifs_match_super(struct super_block *sb, void *data)
2948{
2949 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2950 struct smb_vol *volume_info;
2951 struct cifs_sb_info *cifs_sb;
2952 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002953 struct cifs_ses *ses;
2954 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002955 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002956 int rc = 0;
2957
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002958 spin_lock(&cifs_tcp_ses_lock);
2959 cifs_sb = CIFS_SB(sb);
2960 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2961 if (IS_ERR(tlink)) {
2962 spin_unlock(&cifs_tcp_ses_lock);
2963 return rc;
2964 }
2965 tcon = tlink_tcon(tlink);
2966 ses = tcon->ses;
2967 tcp_srv = ses->server;
2968
2969 volume_info = mnt_data->vol;
2970
Jeff Layton9fa114f2012-11-26 11:09:57 -05002971 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002972 !match_session(ses, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01002973 !match_tcon(tcon, volume_info->UNC) ||
2974 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002975 rc = 0;
2976 goto out;
2977 }
2978
2979 rc = compare_mount_options(sb, mnt_data);
2980out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002981 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002982 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002983 return rc;
2984}
2985
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002987get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002988 const struct nls_table *nls_codepage, unsigned int *num_referrals,
2989 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990{
2991 char *temp_unc;
2992 int rc = 0;
2993
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002994 if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002995 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002997 *num_referrals = 0;
2998 *referrals = NULL;
2999
3000 if (ses->ipc_tid == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 temp_unc = kmalloc(2 /* for slashes */ +
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003002 strnlen(ses->serverName, SERVER_NAME_LEN_WITH_NULL * 2)
3003 + 1 + 4 /* slash IPC$ */ + 2, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 if (temp_unc == NULL)
3005 return -ENOMEM;
3006 temp_unc[0] = '\\';
3007 temp_unc[1] = '\\';
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003008 strcpy(temp_unc + 2, ses->serverName);
3009 strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
3010 rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
3011 nls_codepage);
Joe Perchesf96637b2013-05-04 22:12:25 -05003012 cifs_dbg(FYI, "Tcon rc = %d ipc_tid = %d\n", rc, ses->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 kfree(temp_unc);
3014 }
3015 if (rc == 0)
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003016 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
3017 referrals, num_referrals,
3018 nls_codepage, remap);
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003019 /*
3020 * BB - map targetUNCs to dfs_info3 structures, here or in
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003021 * ses->server->ops->get_dfs_refer.
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003022 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023
3024 return rc;
3025}
3026
Jeff Layton09e50d52008-07-23 10:11:19 -04003027#ifdef CONFIG_DEBUG_LOCK_ALLOC
3028static struct lock_class_key cifs_key[2];
3029static struct lock_class_key cifs_slock_key[2];
3030
3031static inline void
3032cifs_reclassify_socket4(struct socket *sock)
3033{
3034 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003035 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003036 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3037 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3038}
3039
3040static inline void
3041cifs_reclassify_socket6(struct socket *sock)
3042{
3043 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003044 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003045 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3046 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3047}
3048#else
3049static inline void
3050cifs_reclassify_socket4(struct socket *sock)
3051{
3052}
3053
3054static inline void
3055cifs_reclassify_socket6(struct socket *sock)
3056{
3057}
3058#endif
3059
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003061static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062{
Steve French50c2f752007-07-13 00:33:32 +00003063 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064
Steve French50c2f752007-07-13 00:33:32 +00003065 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 /* mask a nibble at a time and encode */
3067 target[j] = 'A' + (0x0F & (source[i] >> 4));
3068 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003069 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 }
3071
3072}
3073
Ben Greear3eb9a882010-09-01 17:06:02 -07003074static int
3075bind_socket(struct TCP_Server_Info *server)
3076{
3077 int rc = 0;
3078 if (server->srcaddr.ss_family != AF_UNSPEC) {
3079 /* Bind to the specified local IP address */
3080 struct socket *socket = server->ssocket;
3081 rc = socket->ops->bind(socket,
3082 (struct sockaddr *) &server->srcaddr,
3083 sizeof(server->srcaddr));
3084 if (rc < 0) {
3085 struct sockaddr_in *saddr4;
3086 struct sockaddr_in6 *saddr6;
3087 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3088 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3089 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05003090 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3091 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003092 else
Joe Perchesf96637b2013-05-04 22:12:25 -05003093 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3094 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003095 }
3096 }
3097 return rc;
3098}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099
3100static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003101ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102{
3103 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003104 /*
3105 * some servers require RFC1001 sessinit before sending
3106 * negprot - BB check reconnection in case where second
3107 * sessinit is sent but no second negprot
3108 */
3109 struct rfc1002_session_packet *ses_init_buf;
3110 struct smb_hdr *smb_buf;
3111 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3112 GFP_KERNEL);
3113 if (ses_init_buf) {
3114 ses_init_buf->trailer.session_req.called_len = 32;
3115
Colin Ian King997152f2016-01-25 16:25:54 +00003116 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003117 rfc1002mangle(ses_init_buf->trailer.
3118 session_req.called_name,
3119 server->server_RFC1001_name,
3120 RFC1001_NAME_LEN_WITH_NULL);
3121 else
3122 rfc1002mangle(ses_init_buf->trailer.
3123 session_req.called_name,
3124 DEFAULT_CIFS_CALLED_NAME,
3125 RFC1001_NAME_LEN_WITH_NULL);
3126
3127 ses_init_buf->trailer.session_req.calling_len = 32;
3128
3129 /*
3130 * calling name ends in null (byte 16) from old smb
3131 * convention.
3132 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003133 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003134 rfc1002mangle(ses_init_buf->trailer.
3135 session_req.calling_name,
3136 server->workstation_RFC1001_name,
3137 RFC1001_NAME_LEN_WITH_NULL);
3138 else
3139 rfc1002mangle(ses_init_buf->trailer.
3140 session_req.calling_name,
3141 "LINUX_CIFS_CLNT",
3142 RFC1001_NAME_LEN_WITH_NULL);
3143
3144 ses_init_buf->trailer.session_req.scope1 = 0;
3145 ses_init_buf->trailer.session_req.scope2 = 0;
3146 smb_buf = (struct smb_hdr *)ses_init_buf;
3147
3148 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003149 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003150 rc = smb_send(server, smb_buf, 0x44);
3151 kfree(ses_init_buf);
3152 /*
3153 * RFC1001 layer in at least one server
3154 * requires very short break before negprot
3155 * presumably because not expecting negprot
3156 * to follow so fast. This is a simple
3157 * solution that works without
3158 * complicating the code and causes no
3159 * significant slowing down on mount
3160 * for everyone else
3161 */
3162 usleep_range(1000, 2000);
3163 }
3164 /*
3165 * else the negprot may still work without this
3166 * even though malloc failed
3167 */
3168
3169 return rc;
3170}
3171
3172static int
3173generic_ip_connect(struct TCP_Server_Info *server)
3174{
3175 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003176 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003177 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003178 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003179 struct sockaddr *saddr;
3180
3181 saddr = (struct sockaddr *) &server->dstaddr;
3182
3183 if (server->dstaddr.ss_family == AF_INET6) {
3184 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3185 slen = sizeof(struct sockaddr_in6);
3186 sfamily = AF_INET6;
3187 } else {
3188 sport = ((struct sockaddr_in *) saddr)->sin_port;
3189 slen = sizeof(struct sockaddr_in);
3190 sfamily = AF_INET;
3191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003193 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003194 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3195 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003197 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003198 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003201
3202 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003203 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003204 server->ssocket = socket;
3205 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003206 if (sfamily == AF_INET6)
3207 cifs_reclassify_socket6(socket);
3208 else
3209 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210 }
3211
Ben Greear3eb9a882010-09-01 17:06:02 -07003212 rc = bind_socket(server);
3213 if (rc < 0)
3214 return rc;
3215
Jeff Laytond5c56052008-12-01 18:42:33 -05003216 /*
3217 * Eventually check for other socket options to change from
3218 * the default. sock_setsockopt not used because it expects
3219 * user space buffer
3220 */
3221 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003222 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003223
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003224 /* make the bufsizes depend on wsize/rsize and max requests */
3225 if (server->noautotune) {
3226 if (socket->sk->sk_sndbuf < (200 * 1024))
3227 socket->sk->sk_sndbuf = 200 * 1024;
3228 if (socket->sk->sk_rcvbuf < (140 * 1024))
3229 socket->sk->sk_rcvbuf = 140 * 1024;
3230 }
3231
Steve French6a5fa2362010-01-01 01:28:43 +00003232 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003233 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003234 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3235 (char *)&val, sizeof(val));
3236 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003237 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3238 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003239 }
3240
Joe Perchesf96637b2013-05-04 22:12:25 -05003241 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003242 socket->sk->sk_sndbuf,
3243 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3244
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003245 rc = socket->ops->connect(socket, saddr, slen, 0);
3246 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003247 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003248 sock_release(socket);
3249 server->ssocket = NULL;
3250 return rc;
3251 }
3252
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003253 if (sport == htons(RFC1001_PORT))
3254 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003255
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 return rc;
3257}
3258
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003259static int
3260ip_connect(struct TCP_Server_Info *server)
3261{
Steve French6da97912011-03-13 18:55:55 +00003262 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003263 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3264 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3265
3266 if (server->dstaddr.ss_family == AF_INET6)
3267 sport = &addr6->sin6_port;
3268 else
3269 sport = &addr->sin_port;
3270
3271 if (*sport == 0) {
3272 int rc;
3273
3274 /* try with 445 port at first */
3275 *sport = htons(CIFS_PORT);
3276
3277 rc = generic_ip_connect(server);
3278 if (rc >= 0)
3279 return rc;
3280
3281 /* if it failed, try with 139 port */
3282 *sport = htons(RFC1001_PORT);
3283 }
3284
3285 return generic_ip_connect(server);
3286}
3287
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003288void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003289 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003290{
3291 /* if we are reconnecting then should we check to see if
3292 * any requested capabilities changed locally e.g. via
3293 * remount but we can not do much about it here
3294 * if they have (even if we could detect it by the following)
3295 * Perhaps we could add a backpointer to array of sb from tcon
3296 * or if we change to make all sb to same share the same
3297 * sb as NFS - then we only have one backpointer to sb.
3298 * What if we wanted to mount the server share twice once with
3299 * and once without posixacls or posix paths? */
3300 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003301
Steve Frenchc18c8422007-07-18 23:21:09 +00003302 if (vol_info && vol_info->no_linux_ext) {
3303 tcon->fsUnixInfo.Capability = 0;
3304 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003305 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003306 return;
3307 } else if (vol_info)
3308 tcon->unix_ext = 1; /* Unix Extensions supported */
3309
3310 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003311 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003312 return;
3313 }
Steve French50c2f752007-07-13 00:33:32 +00003314
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003315 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003316 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003317 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003318 /* check for reconnect case in which we do not
3319 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003320 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003321 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003322 originally at mount time */
3323 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3324 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003325 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3326 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003327 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003328 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003329 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003330 cifs_dbg(VFS, "possible reconnect error\n");
3331 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003332 }
Steve French8af18972007-02-14 04:42:51 +00003333 }
Steve French50c2f752007-07-13 00:33:32 +00003334
Steve French6848b732011-05-26 18:38:54 +00003335 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003336 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003337
Steve French8af18972007-02-14 04:42:51 +00003338 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003339 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003340 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003341 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003342 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003343 if (cifs_sb)
3344 cifs_sb->mnt_cifs_flags |=
3345 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003346 }
3347
Steve French75865f8c2007-06-24 18:30:48 +00003348 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003349 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003350 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003351 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003352 if (cifs_sb)
3353 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003354 CIFS_MOUNT_POSIX_PATHS;
3355 }
Steve French50c2f752007-07-13 00:33:32 +00003356
Joe Perchesf96637b2013-05-04 22:12:25 -05003357 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003358#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003359 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003360 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003361 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003362 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003363 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003364 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003365 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003366 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003367 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003368 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003369 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003370 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003371 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003372 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003373 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003374 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003375 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003376 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003377#endif /* CIFS_DEBUG2 */
3378 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003379 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003380 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003381 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003382 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 +00003383
Steve French8af18972007-02-14 04:42:51 +00003384 }
3385 }
3386}
3387
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003388int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003389 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003390{
Jeff Layton2de970f2010-10-06 19:51:12 -04003391 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3392
Al Viro2ced6f62011-06-17 09:20:04 -04003393 spin_lock_init(&cifs_sb->tlink_tree_lock);
3394 cifs_sb->tlink_tree = RB_ROOT;
3395
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003396 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003397 * Temporarily set r/wsize for matching superblock. If we end up using
3398 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003399 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003400 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003401 cifs_sb->wsize = pvolume_info->wsize;
3402
Steve French3b795212008-11-13 19:45:32 +00003403 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3404 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3405 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3406 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Frank Sorensonccfae492020-02-12 15:31:48 -06003407 cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003408 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003409
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303410 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003411 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303412
Steve French3b795212008-11-13 19:45:32 +00003413 if (pvolume_info->noperm)
3414 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3415 if (pvolume_info->setuids)
3416 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05003417 if (pvolume_info->setuidfromacl)
3418 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00003419 if (pvolume_info->server_ino)
3420 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3421 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003422 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3423 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003424 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3425 if (pvolume_info->no_xattr)
3426 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3427 if (pvolume_info->sfu_emul)
3428 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3429 if (pvolume_info->nobrl)
3430 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003431 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003432 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003433 if (pvolume_info->mand_lock)
3434 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003435 if (pvolume_info->rwpidforward)
3436 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003437 if (pvolume_info->cifs_acl)
3438 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003439 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003440 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003441 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3442 }
3443 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003444 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003445 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3446 }
Steve French3b795212008-11-13 19:45:32 +00003447 if (pvolume_info->override_uid)
3448 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3449 if (pvolume_info->override_gid)
3450 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3451 if (pvolume_info->dynperm)
3452 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303453 if (pvolume_info->fsc)
3454 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003455 if (pvolume_info->multiuser)
3456 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3457 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003458 if (pvolume_info->strict_io)
3459 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003460 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003461 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003462 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3463 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003464 if (pvolume_info->mfsymlinks) {
3465 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003466 /*
3467 * Our SFU ("Services for Unix" emulation does not allow
3468 * creating symlinks but does allow reading existing SFU
3469 * symlinks (it does allow both creating and reading SFU
3470 * style mknod and FIFOs though). When "mfsymlinks" and
3471 * "sfu" are both enabled at the same time, it allows
3472 * reading both types of symlinks, but will only create
3473 * them with mfsymlinks format. This allows better
3474 * Apple compatibility (probably better for Samba too)
3475 * while still recognizing old Windows style symlinks.
3476 */
3477 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003478 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003479 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003480 }
Steve French3b795212008-11-13 19:45:32 +00003481
3482 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003483 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003484
3485 if (pvolume_info->prepath) {
3486 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
3487 if (cifs_sb->prepath == NULL)
3488 return -ENOMEM;
3489 }
3490
3491 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003492}
3493
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003494static void
3495cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003496{
Sean Finneyb9468452011-04-11 13:19:32 +00003497 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003498 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003499 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003500 kfree(volume_info->domainname);
3501 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003502 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003503}
3504
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003505void
3506cifs_cleanup_volume_info(struct smb_vol *volume_info)
3507{
3508 if (!volume_info)
3509 return;
3510 cleanup_volume_info_contents(volume_info);
3511 kfree(volume_info);
3512}
3513
3514
Steve French2d6d5892009-04-09 00:36:44 +00003515#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003516/*
3517 * cifs_build_path_to_root returns full path to root when we do not have an
3518 * exiting connection (tcon)
3519 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003520static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003521build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003522 const struct cifs_sb_info *cifs_sb)
3523{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003524 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003525 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003526 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003527
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003528 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003529 if (full_path == NULL)
3530 return ERR_PTR(-ENOMEM);
3531
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003532 strncpy(full_path, vol->UNC, unc_len);
3533 pos = full_path + unc_len;
3534
3535 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04003536 *pos = CIFS_DIR_SEP(cifs_sb);
3537 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003538 pos += pplen;
3539 }
3540
3541 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003542 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003543 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003544 return full_path;
3545}
Sean Finneydd613942011-04-11 13:19:30 +00003546
3547/*
3548 * Perform a dfs referral query for a share and (optionally) prefix
3549 *
Sean Finney046462a2011-04-11 13:19:33 +00003550 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3551 * to a string containing updated options for the submount. Otherwise it
3552 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003553 *
3554 * Returns the rc from get_dfs_path to the caller, which can be used to
3555 * determine whether there were referrals.
3556 */
3557static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003558expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003559 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003560 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003561{
3562 int rc;
3563 unsigned int num_referrals = 0;
3564 struct dfs_info3_param *referrals = NULL;
3565 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3566
3567 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3568 if (IS_ERR(full_path))
3569 return PTR_ERR(full_path);
3570
3571 /* For DFS paths, skip the first '\' of the UNC */
3572 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3573
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003574 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05003575 &num_referrals, &referrals, cifs_remap(cifs_sb));
Sean Finneydd613942011-04-11 13:19:30 +00003576
3577 if (!rc && num_referrals > 0) {
3578 char *fake_devname = NULL;
3579
3580 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3581 full_path + 1, referrals,
3582 &fake_devname);
3583
3584 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003585
Sean Finneydd613942011-04-11 13:19:30 +00003586 if (IS_ERR(mdata)) {
3587 rc = PTR_ERR(mdata);
3588 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003589 } else {
3590 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003591 rc = cifs_setup_volume_info(volume_info, mdata,
3592 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003593 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003594 kfree(fake_devname);
3595 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003596 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003597 }
3598 kfree(full_path);
3599 return rc;
3600}
Steve French2d6d5892009-04-09 00:36:44 +00003601#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003602
Jeff Layton04db79b2011-07-06 08:10:38 -04003603static int
3604cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3605 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003607 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003608
Jeff Layton04db79b2011-07-06 08:10:38 -04003609 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3610 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611
Jeff Layton7586b762008-12-01 18:41:49 -05003612 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003613 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05003614 kfree(volume_info->username);
3615 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003616 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05003618 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05003620 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00003621 /* In userspace mount helper we can get user name from alternate
3622 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003623 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 }
3625
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003627 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003628 /* load_nls_default cannot return null */
3629 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003631 volume_info->local_nls = load_nls(volume_info->iocharset);
3632 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003633 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003634 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003635 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 }
3637 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003638
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003639 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003640}
3641
3642struct smb_vol *
3643cifs_get_volume_info(char *mount_data, const char *devname)
3644{
3645 int rc;
3646 struct smb_vol *volume_info;
3647
Jeff Layton6ee95422012-11-26 11:09:57 -05003648 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003649 if (!volume_info)
3650 return ERR_PTR(-ENOMEM);
3651
3652 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3653 if (rc) {
3654 cifs_cleanup_volume_info(volume_info);
3655 volume_info = ERR_PTR(rc);
3656 }
3657
3658 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003659}
3660
Aurelien Aptela6b50582016-05-25 19:59:09 +02003661static int
3662cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
3663 unsigned int xid,
3664 struct cifs_tcon *tcon,
3665 struct cifs_sb_info *cifs_sb,
3666 char *full_path)
3667{
3668 int rc;
3669 char *s;
3670 char sep, tmp;
3671
3672 sep = CIFS_DIR_SEP(cifs_sb);
3673 s = full_path;
3674
3675 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
3676 while (rc == 0) {
3677 /* skip separators */
3678 while (*s == sep)
3679 s++;
3680 if (!*s)
3681 break;
3682 /* next separator */
3683 while (*s && *s != sep)
3684 s++;
3685
3686 /*
3687 * temporarily null-terminate the path at the end of
3688 * the current component
3689 */
3690 tmp = *s;
3691 *s = 0;
3692 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3693 full_path);
3694 *s = tmp;
3695 }
3696 return rc;
3697}
3698
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003699int
Al Viro2c6292a2011-06-17 09:05:48 -04003700cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003701{
Jeff Layton1daaae82012-03-21 06:30:40 -04003702 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003703 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003704 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00003705 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003706 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003707 char *full_path;
3708 struct tcon_link *tlink;
3709#ifdef CONFIG_CIFS_DFS_UPCALL
3710 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003711#endif
Al Virodd854462011-06-17 08:24:42 -04003712
Christoph Hellwigb4caecd2015-01-14 10:42:32 +01003713 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs");
Al Virodd854462011-06-17 08:24:42 -04003714 if (rc)
3715 return rc;
3716
Jeff Layton20547492011-07-09 12:21:07 -04003717#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003718try_mount_again:
3719 /* cleanup activities if we're chasing a referral */
3720 if (referral_walks_count) {
3721 if (tcon)
3722 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003723 else if (ses)
3724 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003725
Sachin Prabhu1dfd18d2015-06-16 16:36:17 +01003726 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
3727
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003728 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003729 }
3730#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003731 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003732 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003733 ses = NULL;
3734 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003735 full_path = NULL;
3736 tlink = NULL;
3737
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003738 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739
Jeff Layton63c038c2008-12-01 18:41:46 -05003740 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003741 server = cifs_get_tcp_session(volume_info);
3742 if (IS_ERR(server)) {
3743 rc = PTR_ERR(server);
Al Virodd854462011-06-17 08:24:42 -04003744 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003745 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746 }
Steve French141891f2016-09-23 00:44:16 -05003747 if ((volume_info->max_credits < 20) ||
3748 (volume_info->max_credits > 60000))
3749 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
3750 else
3751 server->max_credits = volume_info->max_credits;
Jeff Layton36988c72010-04-24 07:57:43 -04003752 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003753 ses = cifs_get_smb_ses(server, volume_info);
3754 if (IS_ERR(ses)) {
3755 rc = PTR_ERR(ses);
3756 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04003757 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 }
Steve French50c2f752007-07-13 00:33:32 +00003759
Steve French592fafe2015-11-03 10:08:53 -06003760#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06003761 if ((volume_info->persistent == true) && ((ses->server->capabilities &
3762 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
3763 cifs_dbg(VFS, "persistent handles not supported by server\n");
3764 rc = -EOPNOTSUPP;
3765 goto mount_fail_check;
3766 }
Steve French592fafe2015-11-03 10:08:53 -06003767#endif /* CONFIG_CIFS_SMB2*/
3768
Jeff Laytond00c28d2010-04-24 07:57:44 -04003769 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003770 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003771 if (IS_ERR(tcon)) {
3772 rc = PTR_ERR(tcon);
3773 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003774 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003775 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003776
Steve French6848b732011-05-26 18:38:54 +00003777 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003778 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00003779 /* reset of caps checks mount to see if unix extensions
3780 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003781 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003782 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3783 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3784 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3785 rc = -EACCES;
3786 goto mount_fail_check;
3787 }
3788 } else
3789 tcon->unix_ext = 0; /* server does not support them */
3790
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003791 /* do not care if a following call succeed - informational */
3792 if (!tcon->ipc && server->ops->qfs_tcon)
3793 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00003794
Pavel Shilovsky24985c52012-09-18 16:20:28 -07003795 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
3796 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003797
Jeff Layton66bfaad2011-10-19 15:30:35 -04003798 /* tune readahead according to rsize */
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03003799 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003800
Igor Mammedove4cce942009-02-10 14:10:26 +03003801remote_path_check:
3802#ifdef CONFIG_CIFS_DFS_UPCALL
3803 /*
3804 * Perform an unconditional check for whether there are DFS
3805 * referrals for this path without prefix, to provide support
3806 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003807 * with PATH_NOT_COVERED to requests that include the prefix.
3808 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003809 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003810 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003811 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
3812 false);
Steve Frencheeac8042006-01-13 21:34:58 -08003813 if (!refrc) {
Steve French4523cc32007-04-30 20:13:06 +00003814 referral_walks_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 goto try_mount_again;
3816 }
3817 }
3818#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003819
Steve Frenchf87d39d2011-05-27 03:50:55 +00003820 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003822 if (!server->ops->is_path_accessible) {
3823 rc = -ENOSYS;
3824 goto mount_fail_check;
3825 }
Steve French6d3ea7e2012-11-28 22:34:41 -06003826 /*
3827 * cifs_build_path_to_root works only when we have a valid tcon
3828 */
3829 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 if (full_path == NULL) {
3831 rc = -ENOMEM;
3832 goto mount_fail_check;
3833 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003834 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3835 full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 if (rc != 0 && rc != -EREMOTE) {
3837 kfree(full_path);
3838 goto mount_fail_check;
3839 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02003840
Sachin Prabhud1713562016-09-06 13:22:34 +01003841 if (rc != -EREMOTE) {
3842 rc = cifs_are_all_path_components_accessible(server,
Aurelien Aptela6b50582016-05-25 19:59:09 +02003843 xid, tcon, cifs_sb,
3844 full_path);
Sachin Prabhud1713562016-09-06 13:22:34 +01003845 if (rc != 0) {
3846 cifs_dbg(VFS, "cannot query dirs between root and final path, "
3847 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
3848 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
3849 rc = 0;
3850 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02003851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852 kfree(full_path);
3853 }
3854
3855 /* get referral if needed */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003856 if (rc == -EREMOTE) {
3857#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003858 if (referral_walks_count > MAX_NESTED_LINKS) {
3859 /*
3860 * BB: when we implement proper loop detection,
3861 * we will remove this check. But now we need it
3862 * to prevent an indefinite loop if 'DFS tree' is
3863 * misconfigured (i.e. has loops).
3864 */
3865 rc = -ELOOP;
3866 goto mount_fail_check;
3867 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003868
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003869 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003870
Sean Finneydd613942011-04-11 13:19:30 +00003871 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003872 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003873 goto try_mount_again;
3874 }
Sean Finneydd613942011-04-11 13:19:30 +00003875 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003876#else /* No DFS support, return error on mount */
3877 rc = -EOPNOTSUPP;
3878#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003879 }
3880
Jeff Layton9d002df2010-10-06 19:51:11 -04003881 if (rc)
3882 goto mount_fail_check;
3883
3884 /* now, hang the tcon off of the superblock */
3885 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3886 if (tlink == NULL) {
3887 rc = -ENOMEM;
3888 goto mount_fail_check;
3889 }
3890
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003891 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003892 tlink->tl_tcon = tcon;
3893 tlink->tl_time = jiffies;
3894 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3895 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3896
Jeff Layton413e6612010-10-28 13:33:38 -04003897 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003898 spin_lock(&cifs_sb->tlink_tree_lock);
3899 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3900 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003901
Jeff Laytonda472fc2012-03-23 14:40:53 -04003902 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003903 TLINK_IDLE_EXPIRE);
3904
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003905mount_fail_check:
3906 /* on error free sesinfo and tcon struct if needed */
3907 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003908 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003909 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003910 if (tcon)
3911 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003912 else if (ses)
3913 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003914 else
Pavel Shilovsky48f95262016-11-04 11:50:31 -07003915 cifs_put_tcp_session(server, 0);
Al Virodd854462011-06-17 08:24:42 -04003916 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003917 }
3918
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003920 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 return rc;
3922}
3923
Jeff Layton8d1bca32011-06-11 21:17:10 -04003924/*
3925 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3926 * pointer may be NULL.
3927 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003929CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00003930 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 const struct nls_table *nls_codepage)
3932{
3933 struct smb_hdr *smb_buffer;
3934 struct smb_hdr *smb_buffer_response;
3935 TCONX_REQ *pSMB;
3936 TCONX_RSP *pSMBr;
3937 unsigned char *bcc_ptr;
3938 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003939 int length;
3940 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941
3942 if (ses == NULL)
3943 return -EIO;
3944
3945 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003946 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003948
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 smb_buffer_response = smb_buffer;
3950
3951 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3952 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003953
Pavel Shilovsky88257362012-05-23 14:01:59 +04003954 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955 smb_buffer->Uid = ses->Suid;
3956 pSMB = (TCONX_REQ *) smb_buffer;
3957 pSMBr = (TCONX_RSP *) smb_buffer_response;
3958
3959 pSMB->AndXCommand = 0xFF;
3960 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003962 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003963 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003964 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003965 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003966 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003967 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003968 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003969 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3970 specified as required (when that support is added to
3971 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003972 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003973 by Samba (not sure whether other servers allow
3974 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003975#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003976 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05003977 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003978 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003979 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003980 SECMODE_PW_ENCRYPT ? true : false,
3981 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003982 else
3983#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003984 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003985 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05003986 if (rc) {
3987 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
3988 __func__, rc);
3989 cifs_buf_release(smb_buffer);
3990 return rc;
3991 }
Steve Frencheeac8042006-01-13 21:34:58 -08003992
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003993 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003994 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003995 /* must align unicode strings */
3996 *bcc_ptr = 0; /* null byte password */
3997 bcc_ptr++;
3998 }
Steve Frencheeac8042006-01-13 21:34:58 -08003999 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000
Jeff Layton38d77c52013-05-26 07:01:00 -04004001 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4003
4004 if (ses->capabilities & CAP_STATUS32) {
4005 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
4006 }
4007 if (ses->capabilities & CAP_DFS) {
4008 smb_buffer->Flags2 |= SMBFLG2_DFS;
4009 }
4010 if (ses->capabilities & CAP_UNICODE) {
4011 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
4012 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06004013 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004014 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004015 (/* server len*/ + 256 /* share len */), nls_codepage);
4016 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 bcc_ptr += 2; /* skip trailing null */
4018 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019 strcpy(bcc_ptr, tree);
4020 bcc_ptr += strlen(tree) + 1;
4021 }
4022 strcpy(bcc_ptr, "?????");
4023 bcc_ptr += strlen("?????");
4024 bcc_ptr += 1;
4025 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004026 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4027 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 pSMB->ByteCount = cpu_to_le16(count);
4029
Steve French133672e2007-11-13 22:41:37 +00004030 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004031 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 /* above now done in SendReceive */
4034 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004035 bool is_unicode;
4036
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004038 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 tcon->tid = smb_buffer_response->Tid;
4040 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004041 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004042 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004043 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4044 is_unicode = true;
4045 else
4046 is_unicode = false;
4047
Jeff Laytoncc20c032009-04-30 07:16:21 -04004048
Steve French50c2f752007-07-13 00:33:32 +00004049 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004050 if (length == 3) {
4051 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4052 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004053 cifs_dbg(FYI, "IPC connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004054 tcon->ipc = 1;
4055 }
4056 } else if (length == 2) {
4057 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4058 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05004059 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004060 }
4061 }
Steve French50c2f752007-07-13 00:33:32 +00004062 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004063 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05004064 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04004065
4066 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004067 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004068 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004069 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004070 nls_codepage);
4071
Joe Perchesf96637b2013-05-04 22:12:25 -05004072 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004073
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004074 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004075 (smb_buffer_response->WordCount == 7))
4076 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004077 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4078 else
4079 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05004080 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004082 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 ses->ipc_tid = smb_buffer_response->Tid;
4084 }
4085
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004086 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 return rc;
4088}
4089
Al Viro2e32cf52013-10-03 12:53:37 -04004090static void delayed_free(struct rcu_head *p)
4091{
4092 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
4093 unload_nls(sbi->local_nls);
4094 kfree(sbi);
4095}
4096
Al Viro2a9b9952011-06-17 09:27:16 -04004097void
4098cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099{
Jeff Laytonb647c352010-10-28 11:16:44 -04004100 struct rb_root *root = &cifs_sb->tlink_tree;
4101 struct rb_node *node;
4102 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103
Jeff Layton2de970f2010-10-06 19:51:12 -04004104 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4105
Jeff Laytonb647c352010-10-28 11:16:44 -04004106 spin_lock(&cifs_sb->tlink_tree_lock);
4107 while ((node = rb_first(root))) {
4108 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4109 cifs_get_tlink(tlink);
4110 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4111 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004112
Jeff Laytonb647c352010-10-28 11:16:44 -04004113 spin_unlock(&cifs_sb->tlink_tree_lock);
4114 cifs_put_tlink(tlink);
4115 spin_lock(&cifs_sb->tlink_tree_lock);
4116 }
4117 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004118
Al Virodd854462011-06-17 08:24:42 -04004119 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04004120 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02004121 kfree(cifs_sb->prepath);
Al Viro2e32cf52013-10-03 12:53:37 -04004122 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00004123}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004125int
4126cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127{
4128 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004129 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004131 if (!server->ops->need_neg || !server->ops->negotiate)
4132 return -ENOSYS;
4133
Jeff Layton198b5682010-04-24 07:57:48 -04004134 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004135 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04004136 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137
Pavel Shilovsky45275782012-05-17 17:53:29 +04004138 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004139
4140 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04004141 if (rc == 0) {
4142 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004143 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004144 server->tcpStatus = CifsGood;
4145 else
4146 rc = -EHOSTDOWN;
4147 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 }
Steve French26b994f2008-08-06 05:11:33 +00004149
Jeff Layton198b5682010-04-24 07:57:48 -04004150 return rc;
4151}
Steve French26b994f2008-08-06 05:11:33 +00004152
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004153int
4154cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
4155 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04004156{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004157 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04004158 struct TCP_Server_Info *server = ses->server;
4159
Jeff Layton198b5682010-04-24 07:57:48 -04004160 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004161 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004162 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00004163
Joe Perchesf96637b2013-05-04 22:12:25 -05004164 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00004165 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004166
Shu Wangb6a77c72017-09-08 18:48:33 +08004167 if (ses->auth_key.response) {
4168 cifs_dbg(VFS, "Free previous auth_key.response = %p\n",
4169 ses->auth_key.response);
4170 kfree(ses->auth_key.response);
4171 ses->auth_key.response = NULL;
4172 ses->auth_key.len = 0;
4173 }
4174
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004175 if (server->ops->sess_setup)
4176 rc = server->ops->sess_setup(xid, ses, nls_info);
4177
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05004178 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05004179 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004180
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 return rc;
4182}
4183
Jeff Layton8a8798a2012-01-17 16:09:15 -05004184static int
4185cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4186{
Jeff Layton3f618222013-06-12 19:52:14 -05004187 vol->sectype = ses->sectype;
4188
4189 /* krb5 is special, since we don't need username or pw */
4190 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05004191 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05004192
4193 return cifs_set_cifscreds(vol, ses);
4194}
4195
Steve French96daf2b2011-05-27 04:34:02 +00004196static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004197cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04004198{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004199 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004200 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4201 struct cifs_ses *ses;
4202 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004203 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004204
4205 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004206 if (vol_info == NULL)
4207 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004208
Jeff Layton9d002df2010-10-06 19:51:11 -04004209 vol_info->local_nls = cifs_sb->local_nls;
4210 vol_info->linux_uid = fsuid;
4211 vol_info->cred_uid = fsuid;
4212 vol_info->UNC = master_tcon->treeName;
4213 vol_info->retry = master_tcon->retry;
4214 vol_info->nocase = master_tcon->nocase;
4215 vol_info->local_lease = master_tcon->local_lease;
4216 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004217 vol_info->sectype = master_tcon->ses->sectype;
4218 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004219
Jeff Layton8a8798a2012-01-17 16:09:15 -05004220 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4221 if (rc) {
4222 tcon = ERR_PTR(rc);
4223 goto out;
4224 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004225
4226 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304227 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004228 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304229 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004230
4231 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4232 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004233 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky48f95262016-11-04 11:50:31 -07004234 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04004235 goto out;
4236 }
4237
4238 tcon = cifs_get_tcon(ses, vol_info);
4239 if (IS_ERR(tcon)) {
4240 cifs_put_smb_ses(ses);
4241 goto out;
4242 }
4243
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004244 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004245 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4246out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004247 kfree(vol_info->username);
Aurelien Aptel7e689162018-01-25 15:59:39 +01004248 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004249 kfree(vol_info);
4250
4251 return tcon;
4252}
4253
Steve French96daf2b2011-05-27 04:34:02 +00004254struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004255cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4256{
4257 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4258}
4259
Jeff Laytonb647c352010-10-28 11:16:44 -04004260/* find and return a tlink with given uid */
4261static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004262tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04004263{
4264 struct rb_node *node = root->rb_node;
4265 struct tcon_link *tlink;
4266
4267 while (node) {
4268 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4269
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004270 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004271 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004272 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004273 node = node->rb_right;
4274 else
4275 return tlink;
4276 }
4277 return NULL;
4278}
4279
4280/* insert a tcon_link into the tree */
4281static void
4282tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4283{
4284 struct rb_node **new = &(root->rb_node), *parent = NULL;
4285 struct tcon_link *tlink;
4286
4287 while (*new) {
4288 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4289 parent = *new;
4290
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004291 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004292 new = &((*new)->rb_left);
4293 else
4294 new = &((*new)->rb_right);
4295 }
4296
4297 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4298 rb_insert_color(&new_tlink->tl_rbnode, root);
4299}
4300
Jeff Layton9d002df2010-10-06 19:51:11 -04004301/*
4302 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4303 * current task.
4304 *
4305 * If the superblock doesn't refer to a multiuser mount, then just return
4306 * the master tcon for the mount.
4307 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304308 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004309 * exists, then check to see if it's pending construction. If it is then wait
4310 * for construction to complete. Once it's no longer pending, check to see if
4311 * it failed and either return an error or retry construction, depending on
4312 * the timeout.
4313 *
4314 * If one doesn't exist then insert a new tcon_link struct into the tree and
4315 * try to construct a new one.
4316 */
4317struct tcon_link *
4318cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4319{
4320 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004321 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004322 struct tcon_link *tlink, *newtlink;
4323
4324 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4325 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4326
4327 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004328 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004329 if (tlink)
4330 cifs_get_tlink(tlink);
4331 spin_unlock(&cifs_sb->tlink_tree_lock);
4332
4333 if (tlink == NULL) {
4334 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4335 if (newtlink == NULL)
4336 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004337 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004338 newtlink->tl_tcon = ERR_PTR(-EACCES);
4339 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4340 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4341 cifs_get_tlink(newtlink);
4342
Jeff Layton9d002df2010-10-06 19:51:11 -04004343 spin_lock(&cifs_sb->tlink_tree_lock);
4344 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004345 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004346 if (tlink) {
4347 cifs_get_tlink(tlink);
4348 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004349 kfree(newtlink);
4350 goto wait_for_construction;
4351 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004352 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004353 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4354 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004355 } else {
4356wait_for_construction:
4357 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04004358 TASK_INTERRUPTIBLE);
4359 if (ret) {
4360 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10004361 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04004362 }
4363
4364 /* if it's good, return it */
4365 if (!IS_ERR(tlink->tl_tcon))
4366 return tlink;
4367
4368 /* return error if we tried this already recently */
4369 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4370 cifs_put_tlink(tlink);
4371 return ERR_PTR(-EACCES);
4372 }
4373
4374 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4375 goto wait_for_construction;
4376 }
4377
4378 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4379 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4380 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4381
4382 if (IS_ERR(tlink->tl_tcon)) {
4383 cifs_put_tlink(tlink);
4384 return ERR_PTR(-EACCES);
4385 }
4386
4387 return tlink;
4388}
Jeff Layton2de970f2010-10-06 19:51:12 -04004389
4390/*
4391 * periodic workqueue job that scans tcon_tree for a superblock and closes
4392 * out tcons.
4393 */
4394static void
4395cifs_prune_tlinks(struct work_struct *work)
4396{
4397 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4398 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004399 struct rb_root *root = &cifs_sb->tlink_tree;
4400 struct rb_node *node = rb_first(root);
4401 struct rb_node *tmp;
4402 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004403
Jeff Laytonb647c352010-10-28 11:16:44 -04004404 /*
4405 * Because we drop the spinlock in the loop in order to put the tlink
4406 * it's not guarded against removal of links from the tree. The only
4407 * places that remove entries from the tree are this function and
4408 * umounts. Because this function is non-reentrant and is canceled
4409 * before umount can proceed, this is safe.
4410 */
4411 spin_lock(&cifs_sb->tlink_tree_lock);
4412 node = rb_first(root);
4413 while (node != NULL) {
4414 tmp = node;
4415 node = rb_next(tmp);
4416 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4417
4418 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4419 atomic_read(&tlink->tl_count) != 0 ||
4420 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4421 continue;
4422
4423 cifs_get_tlink(tlink);
4424 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4425 rb_erase(tmp, root);
4426
Jeff Layton2de970f2010-10-06 19:51:12 -04004427 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004428 cifs_put_tlink(tlink);
4429 spin_lock(&cifs_sb->tlink_tree_lock);
4430 }
4431 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004432
Jeff Laytonda472fc2012-03-23 14:40:53 -04004433 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004434 TLINK_IDLE_EXPIRE);
4435}