blob: 80ef165d5f33f4dbd3282c2d7ccb42552faf0a60 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/connect.c
3 *
Steve French1080ef72011-02-24 18:07:19 +00004 * Copyright (C) International Business Machines Corp., 2002,2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
Steve Frenchfb8c4b12007-07-10 01:16:18 +000019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010024#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/list.h>
26#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090027#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/pagemap.h>
29#include <linux/ctype.h>
30#include <linux/utsname.h>
31#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070032#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070033#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000034#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070035#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080036#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040037#include <linux/namei.h>
Andrew Lunnc6e970a2017-03-28 23:45:06 +020038#include <linux/uuid.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080039#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040041#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040042#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050043#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000044#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040045#include <linux/parser.h>
Christoph Hellwig2f8b5442016-11-01 07:40:13 -060046#include <linux/bvec.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include "cifspdu.h"
48#include "cifsglob.h"
49#include "cifsproto.h"
50#include "cifs_unicode.h"
51#include "cifs_debug.h"
52#include "cifs_fs_sb.h"
53#include "ntlmssp.h"
54#include "nterr.h"
55#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053056#include "fscache.h"
Pavel Shilovsky53e0e112016-11-04 11:50:31 -070057#include "smb2proto.h"
Long Li2f894642017-11-22 17:38:34 -070058#include "smbdirect.h"
Paulo Alcantara1c780222018-11-14 16:24:03 -020059#include "dns_resolve.h"
Paulo Alcantara93d5cb52018-11-14 17:13:25 -020060#include "cifsfs.h"
Paulo Alcantara1c780222018-11-14 16:24:03 -020061#ifdef CONFIG_CIFS_DFS_UPCALL
62#include "dfs_cache.h"
63#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Linus Torvalds1da177e2005-04-16 15:20:36 -070065extern mempool_t *cifs_req_poolp;
Steve Frenchf92a7202018-05-24 04:11:07 -050066extern bool disable_legacy_dialects;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Jeff Layton2de970f2010-10-06 19:51:12 -040068/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040069#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040070#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040071
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040072enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040073 /* Mount options that take no arguments */
74 Opt_user_xattr, Opt_nouser_xattr,
75 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040076 Opt_forcegid, Opt_noforcegid,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040077 Opt_noblocksend, Opt_noautotune,
78 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
Steve French2baa2682014-09-27 02:19:01 -050079 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040080 Opt_mapchars, Opt_nomapchars, Opt_sfu,
81 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
Steve Frenchb3266142018-05-20 23:41:10 -050082 Opt_noposixpaths, Opt_nounix, Opt_unix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040083 Opt_nocase,
84 Opt_brl, Opt_nobrl,
Steve French3d4ef9a2018-04-25 22:19:09 -050085 Opt_handlecache, Opt_nohandlecache,
Steve French95932652016-09-23 01:36:34 -050086 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040087 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
88 Opt_nohard, Opt_nosoft,
89 Opt_nointr, Opt_intr,
90 Opt_nostrictsync, Opt_strictsync,
91 Opt_serverino, Opt_noserverino,
92 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
93 Opt_acl, Opt_noacl, Opt_locallease,
Jeff Layton1b359202012-09-19 15:20:27 -070094 Opt_sign, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040095 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -040096 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -050097 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -060098 Opt_resilient, Opt_noresilient,
Long Li8339dd32017-11-07 01:54:55 -070099 Opt_domainauto, Opt_rdma,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400100
101 /* Mount options which take numeric value */
102 Opt_backupuid, Opt_backupgid, Opt_uid,
103 Opt_cruid, Opt_gid, Opt_file_mode,
104 Opt_dirmode, Opt_port,
105 Opt_rsize, Opt_wsize, Opt_actimeo,
Steve French141891f2016-09-23 00:44:16 -0500106 Opt_echo_interval, Opt_max_credits,
Steve French8b217fe2016-11-11 22:36:20 -0600107 Opt_snapshot,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400108
109 /* Mount options which take string value */
110 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400111 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400112 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400113 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400114
115 /* Mount options to be ignored */
116 Opt_ignore,
117
118 /* Options which could be blank */
119 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100120 Opt_blank_user,
121 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400122
123 Opt_err
124};
125
126static const match_table_t cifs_mount_option_tokens = {
127
128 { Opt_user_xattr, "user_xattr" },
129 { Opt_nouser_xattr, "nouser_xattr" },
130 { Opt_forceuid, "forceuid" },
131 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400132 { Opt_forcegid, "forcegid" },
133 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400134 { Opt_noblocksend, "noblocksend" },
135 { Opt_noautotune, "noautotune" },
136 { Opt_hard, "hard" },
137 { Opt_soft, "soft" },
138 { Opt_perm, "perm" },
139 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500140 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400141 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500142 { Opt_mapposix, "mapposix" }, /* SFM style */
143 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400144 { Opt_sfu, "sfu" },
145 { Opt_nosfu, "nosfu" },
146 { Opt_nodfs, "nodfs" },
147 { Opt_posixpaths, "posixpaths" },
148 { Opt_noposixpaths, "noposixpaths" },
149 { Opt_nounix, "nounix" },
150 { Opt_nounix, "nolinux" },
Steve Frenchb3266142018-05-20 23:41:10 -0500151 { Opt_nounix, "noposix" },
152 { Opt_unix, "unix" },
153 { Opt_unix, "linux" },
154 { Opt_unix, "posix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400155 { Opt_nocase, "nocase" },
156 { Opt_nocase, "ignorecase" },
157 { Opt_brl, "brl" },
158 { Opt_nobrl, "nobrl" },
Steve French3d4ef9a2018-04-25 22:19:09 -0500159 { Opt_handlecache, "handlecache" },
160 { Opt_nohandlecache, "nohandlecache" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400161 { Opt_nobrl, "nolock" },
162 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400163 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400164 { Opt_setuids, "setuids" },
165 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500166 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400167 { Opt_dynperm, "dynperm" },
168 { Opt_nodynperm, "nodynperm" },
169 { Opt_nohard, "nohard" },
170 { Opt_nosoft, "nosoft" },
171 { Opt_nointr, "nointr" },
172 { Opt_intr, "intr" },
173 { Opt_nostrictsync, "nostrictsync" },
174 { Opt_strictsync, "strictsync" },
175 { Opt_serverino, "serverino" },
176 { Opt_noserverino, "noserverino" },
177 { Opt_rwpidforward, "rwpidforward" },
178 { Opt_cifsacl, "cifsacl" },
179 { Opt_nocifsacl, "nocifsacl" },
180 { Opt_acl, "acl" },
181 { Opt_noacl, "noacl" },
182 { Opt_locallease, "locallease" },
183 { Opt_sign, "sign" },
184 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400185 { Opt_noac, "noac" },
186 { Opt_fsc, "fsc" },
187 { Opt_mfsymlinks, "mfsymlinks" },
188 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400189 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400190 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500191 { Opt_persistent, "persistenthandles"},
192 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600193 { Opt_resilient, "resilienthandles"},
194 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530195 { Opt_domainauto, "domainauto"},
Long Li8339dd32017-11-07 01:54:55 -0700196 { Opt_rdma, "rdma"},
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400197
198 { Opt_backupuid, "backupuid=%s" },
199 { Opt_backupgid, "backupgid=%s" },
200 { Opt_uid, "uid=%s" },
201 { Opt_cruid, "cruid=%s" },
202 { Opt_gid, "gid=%s" },
203 { Opt_file_mode, "file_mode=%s" },
204 { Opt_dirmode, "dirmode=%s" },
205 { Opt_dirmode, "dir_mode=%s" },
206 { Opt_port, "port=%s" },
207 { Opt_rsize, "rsize=%s" },
208 { Opt_wsize, "wsize=%s" },
209 { Opt_actimeo, "actimeo=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600210 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500211 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600212 { Opt_snapshot, "snapshot=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400213
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100214 { Opt_blank_user, "user=" },
215 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400216 { Opt_user, "user=%s" },
217 { Opt_user, "username=%s" },
218 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100219 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400220 { Opt_pass, "pass=%s" },
221 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100222 { Opt_blank_ip, "ip=" },
223 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400224 { Opt_ip, "ip=%s" },
225 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400226 { Opt_ignore, "unc=%s" },
227 { Opt_ignore, "target=%s" },
228 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400229 { Opt_domain, "dom=%s" },
230 { Opt_domain, "domain=%s" },
231 { Opt_domain, "workgroup=%s" },
232 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400233 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400234 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400235 { Opt_netbiosname, "netbiosname=%s" },
236 { Opt_servern, "servern=%s" },
237 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400238 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400239 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400240 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400241
242 { Opt_ignore, "cred" },
243 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400244 { Opt_ignore, "cred=%s" },
245 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400246 { Opt_ignore, "guest" },
247 { Opt_ignore, "rw" },
248 { Opt_ignore, "ro" },
249 { Opt_ignore, "suid" },
250 { Opt_ignore, "nosuid" },
251 { Opt_ignore, "exec" },
252 { Opt_ignore, "noexec" },
253 { Opt_ignore, "nodev" },
254 { Opt_ignore, "noauto" },
255 { Opt_ignore, "dev" },
256 { Opt_ignore, "mand" },
257 { Opt_ignore, "nomand" },
Steve French9b9c5be2018-09-22 12:07:06 -0500258 { Opt_ignore, "relatime" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400259 { Opt_ignore, "_netdev" },
260
261 { Opt_err, NULL }
262};
263
264enum {
265 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
266 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400267 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
268 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400269 Opt_sec_none,
270
271 Opt_sec_err
272};
273
274static const match_table_t cifs_secflavor_tokens = {
275 { Opt_sec_krb5, "krb5" },
276 { Opt_sec_krb5i, "krb5i" },
277 { Opt_sec_krb5p, "krb5p" },
278 { Opt_sec_ntlmsspi, "ntlmsspi" },
279 { Opt_sec_ntlmssp, "ntlmssp" },
280 { Opt_ntlm, "ntlm" },
281 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400282 { Opt_sec_ntlmv2, "nontlm" },
283 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400284 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400285 { Opt_sec_lanman, "lanman" },
286 { Opt_sec_none, "none" },
287
288 { Opt_sec_err, NULL }
289};
290
Jeff Layton15b6a472012-05-16 07:50:15 -0400291/* cache flavors */
292enum {
293 Opt_cache_loose,
294 Opt_cache_strict,
295 Opt_cache_none,
296 Opt_cache_err
297};
298
299static const match_table_t cifs_cacheflavor_tokens = {
300 { Opt_cache_loose, "loose" },
301 { Opt_cache_strict, "strict" },
302 { Opt_cache_none, "none" },
303 { Opt_cache_err, NULL }
304};
305
Jeff Layton23db65f2012-05-15 12:20:51 -0400306static const match_table_t cifs_smb_version_tokens = {
307 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600308 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000309 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500310 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500311 { Smb_302, SMB302_VERSION_STRING },
Kenneth D'souza4a3b38a2018-11-17 10:33:30 +0530312 { Smb_302, ALT_SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600313 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500314 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French9764c022017-09-17 10:41:35 -0500315 { Smb_3any, SMB3ANY_VERSION_STRING },
316 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600317 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400318};
319
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300320static int ip_connect(struct TCP_Server_Info *server);
321static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400322static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400323static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400324static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -0500325 const char *devname, bool is_smb3);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200326static char *extract_hostname(const char *unc);
327
328#ifdef CONFIG_CIFS_DFS_UPCALL
329struct super_cb_data {
330 struct TCP_Server_Info *server;
331 struct cifs_sb_info *cifs_sb;
332};
333
334/* These functions must be called with server->srv_mutex held */
335
336static void super_cb(struct super_block *sb, void *arg)
337{
338 struct super_cb_data *d = arg;
339 struct cifs_sb_info *cifs_sb;
340 struct cifs_tcon *tcon;
341
342 if (d->cifs_sb)
343 return;
344
345 cifs_sb = CIFS_SB(sb);
346 tcon = cifs_sb_master_tcon(cifs_sb);
347 if (tcon->ses->server == d->server)
348 d->cifs_sb = cifs_sb;
349}
350
351static inline struct cifs_sb_info *
352find_super_by_tcp(struct TCP_Server_Info *server)
353{
354 struct super_cb_data d = {
355 .server = server,
356 .cifs_sb = NULL,
357 };
358
359 iterate_supers_type(&cifs_fs_type, super_cb, &d);
360 return d.cifs_sb ? d.cifs_sb : ERR_PTR(-ENOENT);
361}
362
363static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
364 struct cifs_sb_info *cifs_sb,
365 struct dfs_cache_tgt_list *tgt_list,
366 struct dfs_cache_tgt_iterator **tgt_it)
367{
368 const char *name;
369 int rc;
370 char *ipaddr = NULL;
371 char *unc;
372 int len;
373
374 if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list ||
375 !server->nr_targets)
376 return;
377
378 if (!*tgt_it) {
379 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
380 } else {
381 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
382 if (!*tgt_it)
383 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
384 }
385
386 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
387
388 name = dfs_cache_get_tgt_name(*tgt_it);
389
390 kfree(server->hostname);
391
392 server->hostname = extract_hostname(name);
393 if (!server->hostname) {
394 cifs_dbg(FYI, "%s: failed to extract hostname from target: %d\n",
395 __func__, -ENOMEM);
396 return;
397 }
398
399 len = strlen(server->hostname) + 3;
400
401 unc = kmalloc(len, GFP_KERNEL);
402 if (!unc) {
403 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
404 return;
405 }
406 snprintf(unc, len, "\\\\%s", server->hostname);
407
408 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
409 kfree(unc);
410
411 if (rc < 0) {
412 cifs_dbg(FYI, "%s: Failed to resolve server part of %s to IP: %d\n",
413 __func__, server->hostname, rc);
414 return;
415 }
416
417 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
418 strlen(ipaddr));
419 kfree(ipaddr);
420
421 if (!rc) {
422 cifs_dbg(FYI, "%s: failed to get ipaddr out of hostname\n",
423 __func__);
424 }
425}
426
427static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
428 struct dfs_cache_tgt_list *tl,
429 struct dfs_cache_tgt_iterator **it)
430{
431 if (!cifs_sb->origin_fullpath)
432 return -EOPNOTSUPP;
433 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
434}
435#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Jeff Laytond5c56052008-12-01 18:42:33 -0500437/*
438 * cifs tcp session reconnection
439 *
440 * mark tcp session as reconnecting so temporarily locked
441 * mark all smb sessions as reconnecting for tcp session
442 * reconnect tcp session
443 * wake up waiters on reconnection? - (not needed currently)
444 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400445int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446cifs_reconnect(struct TCP_Server_Info *server)
447{
448 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500449 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000450 struct cifs_ses *ses;
451 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000452 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400453 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200454#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara23324402018-11-20 14:37:18 -0200455 struct cifs_sb_info *cifs_sb = NULL;
456 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200457 struct dfs_cache_tgt_iterator *tgt_it = NULL;
458#endif
Steve French50c2f752007-07-13 00:33:32 +0000459
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200461 server->nr_targets = 1;
462#ifdef CONFIG_CIFS_DFS_UPCALL
463 cifs_sb = find_super_by_tcp(server);
464 if (IS_ERR(cifs_sb)) {
465 rc = PTR_ERR(cifs_sb);
466 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
467 __func__, rc);
468 cifs_sb = NULL;
469 } else {
470 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
471 if (rc) {
472 cifs_dbg(VFS, "%s: no target servers for DFS failover\n",
473 __func__);
474 } else {
475 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
476 }
477 }
478 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
479 server->nr_targets);
480#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000481 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000482 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 next time through the loop */
484 spin_unlock(&GlobalMid_Lock);
485 return rc;
486 } else
487 server->tcpStatus = CifsNeedReconnect;
488 spin_unlock(&GlobalMid_Lock);
489 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400490 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
Steve French6e4d3bb2018-09-22 11:25:04 -0500492 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500493 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
495 /* before reconnecting the tcp session, mark the smb session (uid)
496 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500497 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
498 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530499 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500500 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000501 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500502 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500503 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000504 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500505 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100507 if (ses->tcon_ipc)
508 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530510 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500511
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500513 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500514 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000515 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500516 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
517 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800518 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500519 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
520 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 sock_release(server->ssocket);
522 server->ssocket = NULL;
523 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500524 server->sequence_number = 0;
525 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500526 kfree(server->session_key.response);
527 server->session_key.response = NULL;
528 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000529 server->lstrp = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500531 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400532 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500533 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500535 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
536 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400537 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
538 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400539 list_move(&mid_entry->qhead, &retry_list);
540 }
541 spin_unlock(&GlobalMid_Lock);
Rabin Vincent820962d2015-12-23 07:32:41 +0100542 mutex_unlock(&server->srv_mutex);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400543
Joe Perchesf96637b2013-05-04 22:12:25 -0500544 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400545 list_for_each_safe(tmp, tmp2, &retry_list) {
546 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500547 list_del_init(&mid_entry->qhead);
548 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400551 do {
Steve French6c3d8902006-07-31 22:46:20 +0000552 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300553
Jeff Layton73e216a2013-09-05 08:38:10 -0400554 mutex_lock(&server->srv_mutex);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200555 /*
556 * Set up next DFS target server (if any) for reconnect. If DFS
557 * feature is disabled, then we will retry last server we
558 * connected to before.
559 */
Long Li781a8052017-11-22 17:38:36 -0700560 if (cifs_rdma_enabled(server))
561 rc = smbd_reconnect(server);
562 else
563 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000564 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500565 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200566#ifdef CONFIG_CIFS_DFS_UPCALL
567 reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
568 &tgt_it);
569#endif
Federico Sauter4afe2602015-03-17 17:45:28 +0100570 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700571 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 } else {
573 atomic_inc(&tcpSesReconnectCount);
574 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000575 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000576 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000577 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100578 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400580 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500581
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200582#ifdef CONFIG_CIFS_DFS_UPCALL
583 if (tgt_it) {
584 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
585 tgt_it);
586 if (rc) {
587 cifs_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
588 __func__, rc);
589 }
590 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
591 if (rc) {
592 cifs_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
593 __func__, rc);
594 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200595 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200596 }
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200597#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400598 if (server->tcpStatus == CifsNeedNegotiate)
599 mod_delayed_work(cifsiod_wq, &server->echo, 0);
600
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 return rc;
602}
603
Jeff Laytonc74093b2011-01-11 07:24:23 -0500604static void
605cifs_echo_request(struct work_struct *work)
606{
607 int rc;
608 struct TCP_Server_Info *server = container_of(work,
609 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400610 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500611
Jeff Layton247ec9b2011-02-04 17:09:50 -0500612 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400613 * If we need to renegotiate, set echo interval to zero to
614 * immediately call echo service where we can renegotiate.
615 */
616 if (server->tcpStatus == CifsNeedNegotiate)
617 echo_interval = 0;
618 else
619 echo_interval = server->echo_interval;
620
621 /*
622 * We cannot send an echo if it is disabled.
623 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500624 */
Steve French4fcd1812016-06-22 20:12:05 -0500625
626 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400627 server->tcpStatus == CifsExiting ||
628 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400629 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600630 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500631 goto requeue_echo;
632
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400633 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500634 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500635 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
636 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500637
638requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400639 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500640}
641
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400642static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400643allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400644{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400645 if (!server->bigbuf) {
646 server->bigbuf = (char *)cifs_buf_get();
647 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500648 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400649 msleep(3000);
650 /* retry will check if exiting */
651 return false;
652 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400653 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400654 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400655 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400656 }
657
Jeff Layton2a37ef92011-10-19 15:29:23 -0400658 if (!server->smallbuf) {
659 server->smallbuf = (char *)cifs_small_buf_get();
660 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500661 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400662 msleep(1000);
663 /* retry will check if exiting */
664 return false;
665 }
666 /* beginning of smb buffer is cleared in our buf_get */
667 } else {
668 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400669 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400670 }
671
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400672 return true;
673}
674
Jeff Laytonba749e62011-10-11 06:41:32 -0400675static bool
676server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400677{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300678 /*
679 * We need to wait 2 echo intervals to make sure we handle such
680 * situations right:
681 * 1s client sends a normal SMB request
682 * 2s client gets a response
683 * 30s echo workqueue job pops, and decides we got a response recently
684 * and don't need to send another
685 * ...
686 * 65s kernel_recvmsg times out, and we see that we haven't gotten
687 * a response in >60s.
688 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200689 if ((server->tcpStatus == CifsGood ||
690 server->tcpStatus == CifsNeedNegotiate) &&
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600691 time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
692 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
693 server->hostname, (2 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400694 cifs_reconnect(server);
695 wake_up(&server->response_q);
696 return true;
697 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400698
Jeff Laytonba749e62011-10-11 06:41:32 -0400699 return false;
700}
701
Al Viro71335662016-01-09 19:54:50 -0500702static int
703cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400704{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400705 int length = 0;
706 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400707
Al Viro71335662016-01-09 19:54:50 -0500708 smb_msg->msg_control = NULL;
709 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400710
Al Viro71335662016-01-09 19:54:50 -0500711 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500712 try_to_freeze();
713
Al Viro71335662016-01-09 19:54:50 -0500714 if (server_unresponsive(server))
715 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700716 if (cifs_rdma_enabled(server) && server->smbd_conn)
717 length = smbd_recv(server->smbd_conn, smb_msg);
718 else
719 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500720
721 if (server->tcpStatus == CifsExiting)
722 return -ESHUTDOWN;
723
724 if (server->tcpStatus == CifsNeedReconnect) {
725 cifs_reconnect(server);
726 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400727 }
728
Al Viro71335662016-01-09 19:54:50 -0500729 if (length == -ERESTARTSYS ||
730 length == -EAGAIN ||
731 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400732 /*
733 * Minimum sleep to prevent looping, allowing socket
734 * to clear and app threads to set tcpStatus
735 * CifsNeedReconnect if server hung.
736 */
737 usleep_range(1000, 2000);
738 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400739 continue;
Al Viro71335662016-01-09 19:54:50 -0500740 }
741
742 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500743 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400744 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500745 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400746 }
747 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400748 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400749}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400750
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400751int
752cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
753 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400754{
Al Viro71335662016-01-09 19:54:50 -0500755 struct msghdr smb_msg;
756 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100757 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400758
Al Viro71335662016-01-09 19:54:50 -0500759 return cifs_readv_from_socket(server, &smb_msg);
760}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400761
Al Viro71335662016-01-09 19:54:50 -0500762int
763cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700764 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500765{
766 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700767 struct bio_vec bv = {
768 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100769 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500770 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400771}
772
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400773static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400774is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400775{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400776 /*
777 * The first byte big endian of the length field,
778 * is actually not part of the length but the type
779 * with the most common, zero, as regular data.
780 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400781 switch (type) {
782 case RFC1002_SESSION_MESSAGE:
783 /* Regular SMB response */
784 return true;
785 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500786 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400787 break;
788 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500789 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400790 break;
791 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400792 /*
793 * We get this from Windows 98 instead of an error on
794 * SMB negprot response.
795 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500796 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400797 /* give server a second to clean up */
798 msleep(1000);
799 /*
800 * Always try 445 first on reconnect since we get NACK
801 * on some if we ever connected to port 139 (the NACK
802 * is since we do not begin with RFC1001 session
803 * initialize frame).
804 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400805 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400806 cifs_reconnect(server);
807 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400808 break;
809 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500810 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400811 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400812 }
813
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400814 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400815}
816
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400817void
818dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400819{
820#ifdef CONFIG_CIFS_STATS2
821 mid->when_received = jiffies;
822#endif
823 spin_lock(&GlobalMid_Lock);
824 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400825 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400826 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400827 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000828 /*
829 * Trying to handle/dequeue a mid after the send_recv()
830 * function has finished processing it is a bug.
831 */
832 if (mid->mid_flags & MID_DELETED)
833 printk_once(KERN_WARNING
834 "trying to dequeue a deleted mid\n");
835 else
836 list_del_init(&mid->qhead);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400837 spin_unlock(&GlobalMid_Lock);
838}
839
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400840static void
841handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400842 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400843{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400844 if (server->ops->check_trans2 &&
845 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400846 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400847 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400848 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400849 /* Was previous buf put in mpx struct for multi-rsp? */
850 if (!mid->multiRsp) {
851 /* smb buffer will be freed by user thread */
852 if (server->large_buf)
853 server->bigbuf = NULL;
854 else
855 server->smallbuf = NULL;
856 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400857 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400858}
859
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400860static void clean_demultiplex_info(struct TCP_Server_Info *server)
861{
862 int length;
863
864 /* take it off the list, if it's not already */
865 spin_lock(&cifs_tcp_ses_lock);
866 list_del_init(&server->tcp_ses_list);
867 spin_unlock(&cifs_tcp_ses_lock);
868
869 spin_lock(&GlobalMid_Lock);
870 server->tcpStatus = CifsExiting;
871 spin_unlock(&GlobalMid_Lock);
872 wake_up_all(&server->response_q);
873
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400874 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300875 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400876 if (server->credits <= 0)
877 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300878 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400879 /*
880 * Although there should not be any requests blocked on this queue it
881 * can not hurt to be paranoid and try to wake up requests that may
882 * haven been blocked when more than 50 at time were on the wire to the
883 * same server - they now will see the session is in exit state and get
884 * out of SendReceive.
885 */
886 wake_up_all(&server->request_q);
887 /* give those requests time to exit */
888 msleep(125);
Long Libce9ce72017-11-22 17:38:38 -0700889 if (cifs_rdma_enabled(server) && server->smbd_conn) {
890 smbd_destroy(server->smbd_conn);
891 server->smbd_conn = NULL;
892 }
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400893 if (server->ssocket) {
894 sock_release(server->ssocket);
895 server->ssocket = NULL;
896 }
897
898 if (!list_empty(&server->pending_mid_q)) {
899 struct list_head dispose_list;
900 struct mid_q_entry *mid_entry;
901 struct list_head *tmp, *tmp2;
902
903 INIT_LIST_HEAD(&dispose_list);
904 spin_lock(&GlobalMid_Lock);
905 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
906 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500907 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400908 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400909 list_move(&mid_entry->qhead, &dispose_list);
910 }
911 spin_unlock(&GlobalMid_Lock);
912
913 /* now walk dispose list and issue callbacks */
914 list_for_each_safe(tmp, tmp2, &dispose_list) {
915 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500916 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400917 list_del_init(&mid_entry->qhead);
918 mid_entry->callback(mid_entry);
919 }
920 /* 1/8th of sec is more than enough time for them to exit */
921 msleep(125);
922 }
923
924 if (!list_empty(&server->pending_mid_q)) {
925 /*
926 * mpx threads have not exited yet give them at least the smb
927 * send timeout time for long ops.
928 *
929 * Due to delays on oplock break requests, we need to wait at
930 * least 45 seconds before giving up on a request getting a
931 * response and going ahead and killing cifsd.
932 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500933 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400934 msleep(46000);
935 /*
936 * If threads still have not exited they are probably never
937 * coming home not much else we can do but free the memory.
938 */
939 }
940
941 kfree(server->hostname);
942 kfree(server);
943
944 length = atomic_dec_return(&tcpSesAllocCount);
945 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700946 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400947}
948
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400949static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400950standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
951{
952 int length;
953 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +1000954 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400955
956 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100957 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
958 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500959 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400960 cifs_reconnect(server);
961 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400962 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400963 }
964
965 /* switch to large buffer if too big for a small one */
966 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
967 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400968 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400969 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400970 }
971
972 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400973 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100974 pdu_length - HEADER_SIZE(server) + 1
975 + server->vals->header_preamble_size);
976
Jeff Laytone9097ab2011-10-19 15:29:40 -0400977 if (length < 0)
978 return length;
979 server->total_read += length;
980
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400981 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400982
Pavel Shilovsky4326ed22016-11-17 15:24:46 -0800983 return cifs_handle_standard(server, mid);
984}
985
986int
987cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
988{
989 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
990 int length;
991
Jeff Laytone9097ab2011-10-19 15:29:40 -0400992 /*
993 * We know that we received enough to get to the MID as we
994 * checked the pdu_length earlier. Now check to see
995 * if the rest of the header is OK. We borrow the length
996 * var for the rest of the loop to avoid a new stack var.
997 *
998 * 48 bytes is enough to display the header and a little bit
999 * into the payload for debugging purposes.
1000 */
Steve French373512e2015-12-18 13:05:30 -06001001 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001002 if (length != 0)
1003 cifs_dump_mem("Bad SMB: ", buf,
1004 min_t(unsigned int, server->total_read, 48));
1005
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001006 if (server->ops->is_session_expired &&
1007 server->ops->is_session_expired(buf)) {
1008 cifs_reconnect(server);
1009 wake_up(&server->response_q);
1010 return -1;
1011 }
1012
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001013 if (server->ops->is_status_pending &&
1014 server->ops->is_status_pending(buf, server, length))
1015 return -1;
1016
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001017 if (!mid)
1018 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001019
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001020 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001021 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001022}
1023
1024static int
Al Viro7c97c202011-06-21 08:51:28 -04001025cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001027 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001028 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001029 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001030 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001031 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001032 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001033 struct mid_q_entry *mids[MAX_COMPOUND];
1034 char *bufs[MAX_COMPOUND];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -05001037 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001038
1039 length = atomic_inc_return(&tcpSesAllocCount);
1040 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001041 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001043 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +00001044 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001045 if (try_to_freeze())
1046 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001047
Jeff Layton2a37ef92011-10-19 15:29:23 -04001048 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001049 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001050
Jeff Layton2a37ef92011-10-19 15:29:23 -04001051 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001052 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001053 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001054
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001055 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001056 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001057 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001058
1059 if (server->vals->header_preamble_size == 0)
1060 server->total_read = 0;
1061 else
1062 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001063
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001064 /*
1065 * The right amount was read from socket - 4 bytes,
1066 * so we can now interpret the length field.
1067 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001068 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001069
Joe Perchesf96637b2013-05-04 22:12:25 -05001070 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001071 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001072 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001073next_pdu:
1074 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001075
Jeff Layton89482a52011-10-19 15:28:57 -04001076 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001077 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001078 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001079 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001080 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001081 cifs_reconnect(server);
1082 wake_up(&server->response_q);
1083 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001084 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001085
Jeff Layton89482a52011-10-19 15:28:57 -04001086 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001087 length = cifs_read_from_socket(server,
1088 buf + server->vals->header_preamble_size,
1089 HEADER_SIZE(server) - 1
1090 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001091 if (length < 0)
1092 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001093 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001094
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001095 if (server->ops->next_header) {
1096 next_offset = server->ops->next_header(buf);
1097 if (next_offset)
1098 server->pdu_size = next_offset;
1099 }
1100
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001101 memset(mids, 0, sizeof(mids));
1102 memset(bufs, 0, sizeof(bufs));
1103 num_mids = 0;
1104
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001105 if (server->ops->is_transform_hdr &&
1106 server->ops->receive_transform &&
1107 server->ops->is_transform_hdr(buf)) {
1108 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001109 mids,
1110 bufs,
1111 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001112 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001113 mids[0] = server->ops->find_mid(server, buf);
1114 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001115 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001116
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001117 if (!mids[0] || !mids[0]->receive)
1118 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001119 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001120 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001121 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001122
Lars Persson696e4202018-06-25 14:05:25 +02001123 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001124 for (i = 0; i < num_mids; i++)
1125 if (mids[i])
1126 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001127 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001128 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001129
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001130 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -04001131 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -07001132
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001133
Steve Frenchfda35942011-01-20 18:06:34 +00001134 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001135
1136 for (i = 0; i < num_mids; i++) {
1137 if (mids[i] != NULL) {
1138 mids[i]->resp_buf_size = server->pdu_size;
1139 if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
1140 mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
1141 server->ops->handle_cancelled_mid)
1142 server->ops->handle_cancelled_mid(
1143 mids[i]->resp_buf,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001144 server);
1145
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001146 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1147 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001148
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001149 cifs_mid_q_entry_release(mids[i]);
1150 } else if (server->ops->is_oplock_break &&
1151 server->ops->is_oplock_break(bufs[i],
1152 server)) {
1153 cifs_dbg(FYI, "Received oplock break\n");
1154 } else {
1155 cifs_dbg(VFS, "No task to wake, unknown frame "
1156 "received! NumMids %d\n",
1157 atomic_read(&midCount));
1158 cifs_dump_mem("Received Data is: ", bufs[i],
1159 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +00001160#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001161 if (server->ops->dump_detail)
1162 server->ops->dump_detail(bufs[i],
1163 server);
1164 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001165#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001166 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001167 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001168
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001169 if (pdu_length > server->pdu_size) {
1170 if (!allocate_buffers(server))
1171 continue;
1172 pdu_length -= server->pdu_size;
1173 server->total_read = 0;
1174 server->large_buf = false;
1175 buf = server->smallbuf;
1176 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001177 }
1178 } /* end while !EXITING */
1179
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001180 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001181 cifs_buf_release(server->bigbuf);
1182 if (server->smallbuf) /* no sense logging a debug message if NULL */
1183 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001185 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001186 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001187
1188 /* if server->tsk was NULL then wait for a signal before exiting */
1189 if (!task_to_wake) {
1190 set_current_state(TASK_INTERRUPTIBLE);
1191 while (!signal_pending(current)) {
1192 schedule();
1193 set_current_state(TASK_INTERRUPTIBLE);
1194 }
1195 set_current_state(TASK_RUNNING);
1196 }
1197
Jeff Layton0468a2c2008-12-01 07:09:35 -05001198 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199}
1200
Jeff Laytonc359cf32007-11-16 22:22:06 +00001201/* extract the host portion of the UNC string */
1202static char *
1203extract_hostname(const char *unc)
1204{
1205 const char *src;
1206 char *dst, *delim;
1207 unsigned int len;
1208
1209 /* skip double chars at beginning of string */
1210 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001211 if (strlen(unc) < 3)
1212 return ERR_PTR(-EINVAL);
1213 for (src = unc; *src && *src == '\\'; src++)
1214 ;
1215 if (!*src)
1216 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001217
1218 /* delimiter between hostname and sharename is always '\\' now */
1219 delim = strchr(src, '\\');
1220 if (!delim)
1221 return ERR_PTR(-EINVAL);
1222
1223 len = delim - src;
1224 dst = kmalloc((len + 1), GFP_KERNEL);
1225 if (dst == NULL)
1226 return ERR_PTR(-ENOMEM);
1227
1228 memcpy(dst, src, len);
1229 dst[len] = '\0';
1230
1231 return dst;
1232}
1233
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001234static int get_option_ul(substring_t args[], unsigned long *option)
1235{
1236 int rc;
1237 char *string;
1238
1239 string = match_strdup(args);
1240 if (string == NULL)
1241 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001242 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001243 kfree(string);
1244
1245 return rc;
1246}
1247
Eric W. Biederman3da46562013-02-06 01:37:39 -08001248static int get_option_uid(substring_t args[], kuid_t *result)
1249{
1250 unsigned long value;
1251 kuid_t uid;
1252 int rc;
1253
1254 rc = get_option_ul(args, &value);
1255 if (rc)
1256 return rc;
1257
1258 uid = make_kuid(current_user_ns(), value);
1259 if (!uid_valid(uid))
1260 return -EINVAL;
1261
1262 *result = uid;
1263 return 0;
1264}
1265
1266static int get_option_gid(substring_t args[], kgid_t *result)
1267{
1268 unsigned long value;
1269 kgid_t gid;
1270 int rc;
1271
1272 rc = get_option_ul(args, &value);
1273 if (rc)
1274 return rc;
1275
1276 gid = make_kgid(current_user_ns(), value);
1277 if (!gid_valid(gid))
1278 return -EINVAL;
1279
1280 *result = gid;
1281 return 0;
1282}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001283
1284static int cifs_parse_security_flavors(char *value,
1285 struct smb_vol *vol)
1286{
1287
1288 substring_t args[MAX_OPT_ARGS];
1289
Jeff Layton1e3cc572013-06-10 17:12:23 -05001290 /*
1291 * With mount options, the last one should win. Reset any existing
1292 * settings back to default.
1293 */
1294 vol->sectype = Unspecified;
1295 vol->sign = false;
1296
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001297 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001298 case Opt_sec_krb5p:
1299 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1300 return 1;
1301 case Opt_sec_krb5i:
1302 vol->sign = true;
1303 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001304 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001305 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001306 break;
1307 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001308 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001309 /* Fallthrough */
1310 case Opt_sec_ntlmssp:
1311 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001312 break;
1313 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001314 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001315 /* Fallthrough */
1316 case Opt_ntlm:
1317 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001318 break;
1319 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001320 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001321 /* Fallthrough */
1322 case Opt_sec_ntlmv2:
1323 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001324 break;
1325#ifdef CONFIG_CIFS_WEAK_PW_HASH
1326 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001327 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001328 break;
1329#endif
1330 case Opt_sec_none:
1331 vol->nullauth = 1;
1332 break;
1333 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001334 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001335 return 1;
1336 }
1337
1338 return 0;
1339}
1340
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001342cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1343{
1344 substring_t args[MAX_OPT_ARGS];
1345
1346 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1347 case Opt_cache_loose:
1348 vol->direct_io = false;
1349 vol->strict_io = false;
1350 break;
1351 case Opt_cache_strict:
1352 vol->direct_io = false;
1353 vol->strict_io = true;
1354 break;
1355 case Opt_cache_none:
1356 vol->direct_io = true;
1357 vol->strict_io = false;
1358 break;
1359 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001360 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001361 return 1;
1362 }
1363 return 0;
1364}
1365
1366static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001367cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001368{
1369 substring_t args[MAX_OPT_ARGS];
1370
1371 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001372#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001373 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001374 if (disable_legacy_dialects) {
1375 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1376 return 1;
1377 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001378 if (is_smb3) {
1379 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1380 return 1;
1381 }
Jeff Layton23db65f2012-05-15 12:20:51 -04001382 vol->ops = &smb1_operations;
1383 vol->vals = &smb1_values;
1384 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001385 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001386 if (disable_legacy_dialects) {
1387 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1388 return 1;
1389 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001390 if (is_smb3) {
1391 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1392 return 1;
1393 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001394 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001395 vol->vals = &smb20_values;
1396 break;
Steve French74204512018-06-19 14:34:08 -05001397#else
1398 case Smb_1:
1399 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1400 return 1;
1401 case Smb_20:
1402 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1403 return 1;
1404#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001405 case Smb_21:
1406 vol->ops = &smb21_operations;
1407 vol->vals = &smb21_values;
1408 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001409 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001410 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001411 vol->vals = &smb30_values;
1412 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001413 case Smb_302:
1414 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1415 vol->vals = &smb302_values;
1416 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001417 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001418 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001419 vol->vals = &smb311_values;
1420 break;
Steve French9764c022017-09-17 10:41:35 -05001421 case Smb_3any:
1422 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1423 vol->vals = &smb3any_values;
1424 break;
1425 case Smb_default:
1426 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1427 vol->vals = &smbdefault_values;
1428 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001429 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001430 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001431 return 1;
1432 }
1433 return 0;
1434}
1435
Jeff Laytond387a5c2012-12-10 06:10:46 -05001436/*
1437 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1438 * fields with the result. Returns 0 on success and an error otherwise.
1439 */
1440static int
1441cifs_parse_devname(const char *devname, struct smb_vol *vol)
1442{
1443 char *pos;
1444 const char *delims = "/\\";
1445 size_t len;
1446
1447 /* make sure we have a valid UNC double delimiter prefix */
1448 len = strspn(devname, delims);
1449 if (len != 2)
1450 return -EINVAL;
1451
1452 /* find delimiter between host and sharename */
1453 pos = strpbrk(devname + 2, delims);
1454 if (!pos)
1455 return -EINVAL;
1456
1457 /* skip past delimiter */
1458 ++pos;
1459
1460 /* now go until next delimiter or end of string */
1461 len = strcspn(pos, delims);
1462
1463 /* move "pos" up to delimiter or NULL */
1464 pos += len;
1465 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1466 if (!vol->UNC)
1467 return -ENOMEM;
1468
1469 convert_delimiter(vol->UNC, '\\');
1470
Sachin Prabhu11e31642016-02-08 13:44:01 +05301471 /* skip any delimiter */
1472 if (*pos == '/' || *pos == '\\')
1473 pos++;
1474
1475 /* If pos is NULL then no prepath */
1476 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001477 return 0;
1478
1479 vol->prepath = kstrdup(pos, GFP_KERNEL);
1480 if (!vol->prepath)
1481 return -ENOMEM;
1482
1483 return 0;
1484}
1485
Jeff Layton23db65f2012-05-15 12:20:51 -04001486static int
Sean Finneyb9468452011-04-11 13:19:32 +00001487cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001488 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001490 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001491 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 unsigned int temp_len, i, j;
1493 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001494 short int override_uid = -1;
1495 short int override_gid = -1;
1496 bool uid_specified = false;
1497 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001498 bool sloppy = false;
1499 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001500 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001501 char *string = NULL;
1502 char *tmp_end, *value;
1503 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001504 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001505 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001506 unsigned short port = 0;
1507 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
1509 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001510 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001511 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
Jeff Layton6ee95422012-11-26 11:09:57 -05001513 /* ensure we always start with zeroed-out smb_vol */
1514 memset(vol, 0, sizeof(*vol));
1515
Jeff Layton88463992010-11-22 15:31:03 -05001516 /*
1517 * does not have to be perfect mapping since field is
1518 * informational, only used for servers that do not support
1519 * port 445 and it can be overridden at mount time
1520 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001521 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1522 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001523 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1524
Jeff Layton1397f2e2011-01-07 11:30:28 -05001525 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001526 /* null target name indicates to use *SMBSERVR default called name
1527 if we end up sending RFC1001 session initialize */
1528 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001529 vol->cred_uid = current_uid();
1530 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001531 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001532
Steve French2baa2682014-09-27 02:19:01 -05001533 /*
1534 * default to SFM style remapping of seven reserved characters
1535 * unless user overrides it or we negotiate CIFS POSIX where
1536 * it is unnecessary. Can not simultaneously use more than one mapping
1537 * since then readdir could list files that open could not open
1538 */
1539 vol->remap = true;
1540
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001541 /* default to only allowing write access to owner of the mount */
1542 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
1544 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001545 /* default is always to request posix paths. */
1546 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001547 /* default to using server inode numbers where available */
1548 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001549
Jeff Layton1b359202012-09-19 15:20:27 -07001550 /* default is to use strict cifs caching semantics */
1551 vol->strict_io = true;
1552
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301553 vol->actimeo = CIFS_DEF_ACTIMEO;
1554
Steve French9764c022017-09-17 10:41:35 -05001555 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1556 vol->ops = &smb30_operations;
1557 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001558
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001559 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1560
Sean Finneyb9468452011-04-11 13:19:32 +00001561 if (!mountdata)
1562 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Sean Finneyb9468452011-04-11 13:19:32 +00001564 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1565 if (!mountdata_copy)
1566 goto cifs_parse_mount_err;
1567
1568 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001569 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001570
Steve French50c2f752007-07-13 00:33:32 +00001571 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001572 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 separator[0] = options[4];
1574 options += 5;
1575 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001576 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 }
1578 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001579 vol->backupuid_specified = false; /* no backup intent for a user */
1580 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001581
Jeff Layton37d4f992013-05-24 07:40:05 -04001582 switch (cifs_parse_devname(devname, vol)) {
1583 case 0:
1584 break;
1585 case -ENOMEM:
1586 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1587 goto cifs_parse_mount_err;
1588 case -EINVAL:
1589 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1590 goto cifs_parse_mount_err;
1591 default:
1592 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1593 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001594 }
1595
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001597 substring_t args[MAX_OPT_ARGS];
1598 unsigned long option;
1599 int token;
1600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 if (!*data)
1602 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001604 token = match_token(data, cifs_mount_option_tokens, args);
1605
1606 switch (token) {
1607
1608 /* Ingnore the following */
1609 case Opt_ignore:
1610 break;
1611
1612 /* Boolean values */
1613 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001615 break;
1616 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001618 break;
1619 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001620 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001621 break;
1622 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001623 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001624 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001625 case Opt_forcegid:
1626 override_gid = 1;
1627 break;
1628 case Opt_noforcegid:
1629 override_gid = 0;
1630 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001631 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001632 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001633 break;
1634 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001635 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001636 break;
1637 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001639 break;
1640 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001642 break;
1643 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001645 break;
1646 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001648 break;
1649 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001650 vol->sfu_remap = true;
1651 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001652 break;
1653 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001654 vol->sfu_remap = false;
1655 break;
1656 case Opt_mapposix:
1657 vol->remap = true;
1658 vol->sfu_remap = false; /* disable SFU mapping */
1659 break;
1660 case Opt_nomapposix:
1661 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001662 break;
1663 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001664 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001665 break;
1666 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001667 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001668 break;
1669 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001670 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001671 break;
1672 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001673 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001674 break;
1675 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001676 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001677 break;
1678 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001679 if (vol->linux_ext)
1680 cifs_dbg(VFS,
1681 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001682 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001683 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001684 case Opt_unix:
1685 if (vol->no_linux_ext)
1686 cifs_dbg(VFS,
1687 "conflicting unix mount options\n");
1688 vol->linux_ext = 1;
1689 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001690 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001691 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001692 break;
1693 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001694 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001695 break;
1696 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001697 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001698 /*
1699 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001700 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001701 * local vfs will do advisory
1702 */
Steve French50c2f752007-07-13 00:33:32 +00001703 if (vol->file_mode ==
1704 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001705 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001706 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001707 case Opt_nohandlecache:
1708 vol->nohandlecache = 1;
1709 break;
1710 case Opt_handlecache:
1711 vol->nohandlecache = 0;
1712 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001713 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001714 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001715 break;
1716 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001718 break;
1719 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001721 break;
Steve French95932652016-09-23 01:36:34 -05001722 case Opt_setuidfromacl:
1723 vol->setuidfromacl = 1;
1724 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001725 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001726 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001727 break;
1728 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001729 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001730 break;
1731 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001733 break;
1734 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001736 break;
1737 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001739 break;
1740 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001742 break;
1743 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001744 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 break;
1746 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001747 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001748 break;
1749 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001751 break;
1752 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001754 break;
1755 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001756 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001757 break;
1758 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001759 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001760 break;
1761 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001762 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001763 break;
1764 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001766 break;
1767 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001769 break;
1770 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001771 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001772 break;
1773 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001774 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001775 break;
1776 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001777 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001778 * is a per tree connection (mount) not a per socket
1779 * or per-smb connection option in the protocol
1780 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1781 */
Steve French95b1cb92008-05-15 16:44:38 +00001782 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001783 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001784 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001785 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001786 break;
1787 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301788#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001789 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001790 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301791#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301792 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001793 break;
1794 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001795 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001796 break;
1797 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001798 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001799 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001800 case Opt_sloppy:
1801 sloppy = true;
1802 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001803 case Opt_nosharesock:
1804 vol->nosharesock = true;
1805 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001806 case Opt_nopersistent:
1807 vol->nopersistent = true;
1808 if (vol->persistent) {
1809 cifs_dbg(VFS,
1810 "persistenthandles mount options conflict\n");
1811 goto cifs_parse_mount_err;
1812 }
1813 break;
1814 case Opt_persistent:
1815 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001816 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001817 cifs_dbg(VFS,
1818 "persistenthandles mount options conflict\n");
1819 goto cifs_parse_mount_err;
1820 }
1821 break;
Steve French592fafe2015-11-03 10:08:53 -06001822 case Opt_resilient:
1823 vol->resilient = true;
1824 if (vol->persistent) {
1825 cifs_dbg(VFS,
1826 "persistenthandles mount options conflict\n");
1827 goto cifs_parse_mount_err;
1828 }
1829 break;
1830 case Opt_noresilient:
1831 vol->resilient = false; /* already the default */
1832 break;
Germano Percossi39566442016-12-15 12:31:18 +05301833 case Opt_domainauto:
1834 vol->domainauto = true;
1835 break;
Long Li8339dd32017-11-07 01:54:55 -07001836 case Opt_rdma:
1837 vol->rdma = true;
1838 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001839
1840 /* Numeric Values */
1841 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001842 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001843 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1844 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001845 goto cifs_parse_mount_err;
1846 }
1847 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001848 break;
1849 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001850 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001851 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1852 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001853 goto cifs_parse_mount_err;
1854 }
1855 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001856 break;
1857 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001858 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001859 cifs_dbg(VFS, "%s: Invalid uid value\n",
1860 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001861 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001863 uid_specified = true;
1864 break;
1865 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001866 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001867 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1868 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001869 goto cifs_parse_mount_err;
1870 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001871 break;
1872 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001873 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001874 cifs_dbg(VFS, "%s: Invalid gid value\n",
1875 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001876 goto cifs_parse_mount_err;
1877 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001878 gid_specified = true;
1879 break;
1880 case Opt_file_mode:
1881 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001882 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1883 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001884 goto cifs_parse_mount_err;
1885 }
1886 vol->file_mode = option;
1887 break;
1888 case Opt_dirmode:
1889 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001890 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1891 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001892 goto cifs_parse_mount_err;
1893 }
1894 vol->dir_mode = option;
1895 break;
1896 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001897 if (get_option_ul(args, &option) ||
1898 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001899 cifs_dbg(VFS, "%s: Invalid port value\n",
1900 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001901 goto cifs_parse_mount_err;
1902 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001903 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001904 break;
1905 case Opt_rsize:
1906 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001907 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1908 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001909 goto cifs_parse_mount_err;
1910 }
1911 vol->rsize = option;
1912 break;
1913 case Opt_wsize:
1914 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001915 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1916 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001917 goto cifs_parse_mount_err;
1918 }
1919 vol->wsize = option;
1920 break;
1921 case Opt_actimeo:
1922 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001923 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1924 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001925 goto cifs_parse_mount_err;
1926 }
1927 vol->actimeo = HZ * option;
1928 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001929 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001930 goto cifs_parse_mount_err;
1931 }
1932 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06001933 case Opt_echo_interval:
1934 if (get_option_ul(args, &option)) {
1935 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
1936 __func__);
1937 goto cifs_parse_mount_err;
1938 }
1939 vol->echo_interval = option;
1940 break;
Steve French8b217fe2016-11-11 22:36:20 -06001941 case Opt_snapshot:
1942 if (get_option_ul(args, &option)) {
1943 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
1944 __func__);
1945 goto cifs_parse_mount_err;
1946 }
1947 vol->snapshot_time = option;
1948 break;
Steve French141891f2016-09-23 00:44:16 -05001949 case Opt_max_credits:
1950 if (get_option_ul(args, &option) || (option < 20) ||
1951 (option > 60000)) {
1952 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1953 __func__);
1954 goto cifs_parse_mount_err;
1955 }
1956 vol->max_credits = option;
1957 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001958
1959 /* String Arguments */
1960
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001961 case Opt_blank_user:
1962 /* null user, ie. anonymous authentication */
1963 vol->nullauth = 1;
1964 vol->username = NULL;
1965 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001966 case Opt_user:
1967 string = match_strdup(args);
1968 if (string == NULL)
1969 goto out_nomem;
1970
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001971 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1972 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001973 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001974 goto cifs_parse_mount_err;
1975 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001976
1977 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001978 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001979 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001980 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001981 break;
1982 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001983 /* passwords have to be handled differently
1984 * to allow the character used for deliminator
1985 * to be passed within them
1986 */
1987
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001988 /*
1989 * Check if this is a case where the password
1990 * starts with a delimiter
1991 */
1992 tmp_end = strchr(data, '=');
1993 tmp_end++;
1994 if (!(tmp_end < end && tmp_end[1] == delim)) {
1995 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01001996 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001997 vol->password = NULL;
1998 break;
1999 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +11002000 /* Fallthrough - to Opt_pass below.*/
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002001 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002002 /* Obtain the value string */
2003 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002004 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002005
2006 /* Set tmp_end to end of the string */
2007 tmp_end = (char *) value + strlen(value);
2008
2009 /* Check if following character is the deliminator
2010 * If yes, we have encountered a double deliminator
2011 * reset the NULL character to the deliminator
2012 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302013 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002014 tmp_end[0] = delim;
2015
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302016 /* Keep iterating until we get to a single
2017 * deliminator OR the end
2018 */
2019 while ((tmp_end = strchr(tmp_end, delim))
2020 != NULL && (tmp_end[1] == delim)) {
2021 tmp_end = (char *) &tmp_end[2];
2022 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002023
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302024 /* Reset var options to point to next element */
2025 if (tmp_end) {
2026 tmp_end[0] = '\0';
2027 options = (char *) &tmp_end[1];
2028 } else
2029 /* Reached the end of the mount option
2030 * string */
2031 options = end;
2032 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002033
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002034 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002035 /* Now build new password string */
2036 temp_len = strlen(value);
2037 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2038 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002039 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002040 goto cifs_parse_mount_err;
2041 }
2042
2043 for (i = 0, j = 0; i < temp_len; i++, j++) {
2044 vol->password[j] = value[i];
2045 if ((value[i] == delim) &&
2046 value[i+1] == delim)
2047 /* skip the second deliminator */
2048 i++;
2049 }
2050 vol->password[j] = '\0';
2051 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002052 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002053 /* FIXME: should this be an error instead? */
2054 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002055 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002056 case Opt_ip:
2057 string = match_strdup(args);
2058 if (string == NULL)
2059 goto out_nomem;
2060
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002061 if (!cifs_convert_address(dstaddr, string,
2062 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002063 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002064 goto cifs_parse_mount_err;
2065 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002066 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002067 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002068 case Opt_domain:
2069 string = match_strdup(args);
2070 if (string == NULL)
2071 goto out_nomem;
2072
Chen Gang057d6332013-07-19 09:01:36 +08002073 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2074 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002075 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002076 goto cifs_parse_mount_err;
2077 }
2078
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002079 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002080 vol->domainname = kstrdup(string, GFP_KERNEL);
2081 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002082 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002083 goto cifs_parse_mount_err;
2084 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002085 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002086 break;
2087 case Opt_srcaddr:
2088 string = match_strdup(args);
2089 if (string == NULL)
2090 goto out_nomem;
2091
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002092 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002093 (struct sockaddr *)&vol->srcaddr,
2094 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002095 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2096 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002097 goto cifs_parse_mount_err;
2098 }
2099 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002100 case Opt_iocharset:
2101 string = match_strdup(args);
2102 if (string == NULL)
2103 goto out_nomem;
2104
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002105 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002106 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002107 goto cifs_parse_mount_err;
2108 }
2109
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002110 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002111 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002112 vol->iocharset = kstrdup(string,
2113 GFP_KERNEL);
2114 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002115 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002116 goto cifs_parse_mount_err;
2117 }
2118 }
2119 /* if iocharset not set then load_nls_default
2120 * is used by caller
2121 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002122 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002123 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002124 case Opt_netbiosname:
2125 string = match_strdup(args);
2126 if (string == NULL)
2127 goto out_nomem;
2128
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002129 memset(vol->source_rfc1001_name, 0x20,
2130 RFC1001_NAME_LEN);
2131 /*
2132 * FIXME: are there cases in which a comma can
2133 * be valid in workstation netbios name (and
2134 * need special handling)?
2135 */
2136 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2137 /* don't ucase netbiosname for user */
2138 if (string[i] == 0)
2139 break;
2140 vol->source_rfc1001_name[i] = string[i];
2141 }
2142 /* The string has 16th byte zero still from
2143 * set at top of the function
2144 */
2145 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002146 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002147 break;
2148 case Opt_servern:
2149 /* servernetbiosname specified override *SMBSERVER */
2150 string = match_strdup(args);
2151 if (string == NULL)
2152 goto out_nomem;
2153
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002154 /* last byte, type, is 0x20 for servr type */
2155 memset(vol->target_rfc1001_name, 0x20,
2156 RFC1001_NAME_LEN_WITH_NULL);
2157
2158 /* BB are there cases in which a comma can be
2159 valid in this workstation netbios name
2160 (and need special handling)? */
2161
2162 /* user or mount helper must uppercase the
2163 netbios name */
2164 for (i = 0; i < 15; i++) {
2165 if (string[i] == 0)
2166 break;
2167 vol->target_rfc1001_name[i] = string[i];
2168 }
2169 /* The string has 16th byte zero still from
2170 set at top of the function */
2171 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002172 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002173 break;
2174 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002175 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002176 string = match_strdup(args);
2177 if (string == NULL)
2178 goto out_nomem;
2179
Steve French7e682f72017-08-31 21:34:24 -05002180 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002181 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002182 if (strlen(string) > 1) {
2183 pr_warn("Bad mount helper ver=%s. Did "
2184 "you want SMB1 (CIFS) dialect "
2185 "and mean to type vers=1.0 "
2186 "instead?\n", string);
2187 goto cifs_parse_mount_err;
2188 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002189 /* This is the default */
2190 break;
2191 }
2192 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05002193 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002194 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002195 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002196 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002197 string = match_strdup(args);
2198 if (string == NULL)
2199 goto out_nomem;
2200
Steve Frenchc7c137b2018-06-06 17:59:29 -05002201 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002202 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002203 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002204 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002205 case Opt_sec:
2206 string = match_strdup(args);
2207 if (string == NULL)
2208 goto out_nomem;
2209
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002210 if (cifs_parse_security_flavors(string, vol) != 0)
2211 goto cifs_parse_mount_err;
2212 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002213 case Opt_cache:
2214 string = match_strdup(args);
2215 if (string == NULL)
2216 goto out_nomem;
2217
2218 if (cifs_parse_cache_flavor(string, vol) != 0)
2219 goto cifs_parse_mount_err;
2220 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002221 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002222 /*
2223 * An option we don't recognize. Save it off for later
2224 * if we haven't already found one
2225 */
2226 if (!invalid)
2227 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002228 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002230 /* Free up any allocated string */
2231 kfree(string);
2232 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002234
Jeff Laytond8162552012-03-23 14:40:56 -04002235 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002236 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002237 goto cifs_parse_mount_err;
2238 }
2239
Long Li8339dd32017-11-07 01:54:55 -07002240 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2241 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2242 goto cifs_parse_mount_err;
2243 }
2244
Jeff Layton8a8798a2012-01-17 16:09:15 -05002245#ifndef CONFIG_KEYS
2246 /* Muliuser mounts require CONFIG_KEYS support */
2247 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002248 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002249 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002250 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002251#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002252 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002253 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002254 goto cifs_parse_mount_err;
2255 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002256
Jeff Layton62a1a432012-12-10 06:10:45 -05002257 /* make sure UNC has a share name */
2258 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002259 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002260 goto cifs_parse_mount_err;
2261 }
2262
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002263 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002264 int len;
2265 const char *slash;
2266
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002267 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002268 /* Use the address part of the UNC. */
2269 slash = strchr(&vol->UNC[2], '\\');
2270 len = slash - &vol->UNC[2];
2271 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002272 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002273 goto cifs_parse_mount_err;
2274 }
2275 }
2276
2277 /* set the port that we got earlier */
2278 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002280 if (uid_specified)
2281 vol->override_uid = override_uid;
2282 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002283 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002284
2285 if (gid_specified)
2286 vol->override_gid = override_gid;
2287 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002288 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002289
Steve French7e682f72017-08-31 21:34:24 -05002290 if (got_version == false)
2291 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002292 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002293 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002294 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2295 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002296
Sean Finneyb9468452011-04-11 13:19:32 +00002297 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002299
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002300out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002301 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002302cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002303 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002304 kfree(mountdata_copy);
2305 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306}
2307
Ben Greear3eb9a882010-09-01 17:06:02 -07002308/** Returns true if srcaddr isn't specified and rhs isn't
2309 * specified, or if srcaddr is specified and
2310 * matches the IP address of the rhs argument.
2311 */
Jeff Layton45151482010-07-06 20:43:02 -04002312static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002313srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2314{
2315 switch (srcaddr->sa_family) {
2316 case AF_UNSPEC:
2317 return (rhs->sa_family == AF_UNSPEC);
2318 case AF_INET: {
2319 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2320 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2321 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2322 }
2323 case AF_INET6: {
2324 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002325 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002326 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2327 }
2328 default:
2329 WARN_ON(1);
2330 return false; /* don't expect to be here */
2331 }
2332}
2333
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002334/*
2335 * If no port is specified in addr structure, we try to match with 445 port
2336 * and if it fails - with 139 ports. It should be called only if address
2337 * families of server and addr are equal.
2338 */
2339static bool
2340match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2341{
Steve French6da97912011-03-13 18:55:55 +00002342 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002343
2344 switch (addr->sa_family) {
2345 case AF_INET:
2346 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2347 port = ((struct sockaddr_in *) addr)->sin_port;
2348 break;
2349 case AF_INET6:
2350 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2351 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2352 break;
2353 default:
2354 WARN_ON(1);
2355 return false;
2356 }
2357
2358 if (!port) {
2359 port = htons(CIFS_PORT);
2360 if (port == *sport)
2361 return true;
2362
2363 port = htons(RFC1001_PORT);
2364 }
2365
2366 return port == *sport;
2367}
Ben Greear3eb9a882010-09-01 17:06:02 -07002368
2369static bool
2370match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2371 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372{
Jeff Layton45151482010-07-06 20:43:02 -04002373 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002374 case AF_INET: {
2375 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2376 struct sockaddr_in *srv_addr4 =
2377 (struct sockaddr_in *)&server->dstaddr;
2378
2379 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002380 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002381 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002382 }
2383 case AF_INET6: {
2384 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2385 struct sockaddr_in6 *srv_addr6 =
2386 (struct sockaddr_in6 *)&server->dstaddr;
2387
Jeff Layton45151482010-07-06 20:43:02 -04002388 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002389 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002390 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002391 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002392 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002393 break;
2394 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002395 default:
2396 WARN_ON(1);
2397 return false; /* don't expect to be here */
2398 }
Jeff Layton45151482010-07-06 20:43:02 -04002399
Ben Greear3eb9a882010-09-01 17:06:02 -07002400 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2401 return false;
2402
Jeff Layton45151482010-07-06 20:43:02 -04002403 return true;
2404}
2405
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002406static bool
2407match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2408{
Jeff Layton3f618222013-06-12 19:52:14 -05002409 /*
2410 * The select_sectype function should either return the vol->sectype
2411 * that was specified, or "Unspecified" if that sectype was not
2412 * compatible with the given NEGOTIATE request.
2413 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302414 if (server->ops->select_sectype(server, vol->sectype)
2415 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002416 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002417
Jeff Layton3f618222013-06-12 19:52:14 -05002418 /*
2419 * Now check if signing mode is acceptable. No need to check
2420 * global_secflags at this point since if MUST_SIGN is set then
2421 * the server->sign had better be too.
2422 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002423 if (vol->sign && !server->sign)
2424 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002425
2426 return true;
2427}
2428
Jeff Layton9fa114f2012-11-26 11:09:57 -05002429static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002430{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002431 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2432
Jeff Laytona0b3df52013-05-24 07:40:59 -04002433 if (vol->nosharesock)
2434 return 0;
2435
Steve French9764c022017-09-17 10:41:35 -05002436 /* BB update this for smb3any and default case */
Jeff Layton23db65f2012-05-15 12:20:51 -04002437 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2438 return 0;
2439
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002440 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2441 return 0;
2442
2443 if (!match_address(server, addr,
2444 (struct sockaddr *)&vol->srcaddr))
2445 return 0;
2446
2447 if (!match_port(server, addr))
2448 return 0;
2449
2450 if (!match_security(server, vol))
2451 return 0;
2452
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002453 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002454 return 0;
2455
Long Li8339dd32017-11-07 01:54:55 -07002456 if (server->rdma != vol->rdma)
2457 return 0;
2458
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002459 return 1;
2460}
2461
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002462struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002463cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002464{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002465 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302467 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002468 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002469 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002470 continue;
2471
Jeff Laytone7ddee92008-11-14 13:44:38 -05002472 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302473 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002474 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002475 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302477 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 return NULL;
2479}
2480
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002481void
2482cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002484 struct task_struct *task;
2485
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302486 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002487 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302488 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002489 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002491
Rob Landleyf1d0c992011-01-22 15:44:05 -06002492 put_net(cifs_net_ns(server));
2493
Jeff Laytone7ddee92008-11-14 13:44:38 -05002494 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302495 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002496
Jeff Laytonc74093b2011-01-11 07:24:23 -05002497 cancel_delayed_work_sync(&server->echo);
2498
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002499 if (from_reconnect)
2500 /*
2501 * Avoid deadlock here: reconnect work calls
2502 * cifs_put_tcp_session() at its end. Need to be sure
2503 * that reconnect work does nothing with server pointer after
2504 * that step.
2505 */
2506 cancel_delayed_work(&server->reconnect);
2507 else
2508 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002509
Jeff Laytone7ddee92008-11-14 13:44:38 -05002510 spin_lock(&GlobalMid_Lock);
2511 server->tcpStatus = CifsExiting;
2512 spin_unlock(&GlobalMid_Lock);
2513
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002514 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302515 cifs_fscache_release_client_cookie(server);
2516
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002517 kfree(server->session_key.response);
2518 server->session_key.response = NULL;
2519 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002520
2521 task = xchg(&server->tsk, NULL);
2522 if (task)
2523 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524}
2525
Jeff Layton63c038c2008-12-01 18:41:46 -05002526static struct TCP_Server_Info *
2527cifs_get_tcp_session(struct smb_vol *volume_info)
2528{
2529 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002530 int rc;
2531
Joe Perchesf96637b2013-05-04 22:12:25 -05002532 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002533
2534 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002535 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002536 if (tcp_ses)
2537 return tcp_ses;
2538
2539 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2540 if (!tcp_ses) {
2541 rc = -ENOMEM;
2542 goto out_err;
2543 }
2544
Jeff Layton23db65f2012-05-15 12:20:51 -04002545 tcp_ses->ops = volume_info->ops;
2546 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002547 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002548 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2549 if (IS_ERR(tcp_ses->hostname)) {
2550 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002551 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002552 }
2553
2554 tcp_ses->noblocksnd = volume_info->noblocksnd;
2555 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002556 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002557 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002558 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002559 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002560 init_waitqueue_head(&tcp_ses->response_q);
2561 init_waitqueue_head(&tcp_ses->request_q);
2562 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2563 mutex_init(&tcp_ses->srv_mutex);
2564 memcpy(tcp_ses->workstation_RFC1001_name,
2565 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2566 memcpy(tcp_ses->server_RFC1001_name,
2567 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002568 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002569 tcp_ses->sequence_number = 0;
Steve French9e1a37d2018-09-19 02:38:17 -05002570 tcp_ses->reconnect_instance = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002571 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002572 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002573 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2574 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002575 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002576 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2577 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002578 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2579 sizeof(tcp_ses->srcaddr));
2580 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2581 sizeof(tcp_ses->dstaddr));
Steve Frenchfa70b872016-09-22 00:39:34 -05002582 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002583 /*
2584 * at this point we are the only ones with the pointer
2585 * to the struct since the kernel thread not created yet
2586 * no need to spinlock this init of tcpStatus or srv_count
2587 */
2588 tcp_ses->tcpStatus = CifsNew;
2589 ++tcp_ses->srv_count;
2590
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002591 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2592 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2593 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2594 else
2595 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002596 if (tcp_ses->rdma) {
2597#ifndef CONFIG_CIFS_SMB_DIRECT
2598 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2599 rc = -ENOENT;
2600 goto out_err_crypto_release;
2601#endif
2602 tcp_ses->smbd_conn = smbd_get_connection(
2603 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2604 if (tcp_ses->smbd_conn) {
2605 cifs_dbg(VFS, "RDMA transport established\n");
2606 rc = 0;
2607 goto smbd_connected;
2608 } else {
2609 rc = -ENOENT;
2610 goto out_err_crypto_release;
2611 }
2612 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002613 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002614 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002615 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002616 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002617 }
Long Li2f894642017-11-22 17:38:34 -07002618smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002619 /*
2620 * since we're in a cifs function already, we know that
2621 * this will succeed. No need for try_module_get().
2622 */
2623 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002624 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002625 tcp_ses, "cifsd");
2626 if (IS_ERR(tcp_ses->tsk)) {
2627 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002628 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002629 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002630 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002631 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002632 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002633
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002634 tcp_ses->nr_targets = 1;
2635
Jeff Layton63c038c2008-12-01 18:41:46 -05002636 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302637 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002638 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302639 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002640
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302641 cifs_fscache_get_client_cookie(tcp_ses);
2642
Jeff Laytonc74093b2011-01-11 07:24:23 -05002643 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002644 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002645
Jeff Layton63c038c2008-12-01 18:41:46 -05002646 return tcp_ses;
2647
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002648out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002649 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002650
Rob Landleyf1d0c992011-01-22 15:44:05 -06002651 put_net(cifs_net_ns(tcp_ses));
2652
Jeff Layton63c038c2008-12-01 18:41:46 -05002653out_err:
2654 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002655 if (!IS_ERR(tcp_ses->hostname))
2656 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002657 if (tcp_ses->ssocket)
2658 sock_release(tcp_ses->ssocket);
2659 kfree(tcp_ses);
2660 }
2661 return ERR_PTR(rc);
2662}
2663
Steve French96daf2b2011-05-27 04:34:02 +00002664static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002665{
Jeff Layton3f618222013-06-12 19:52:14 -05002666 if (vol->sectype != Unspecified &&
2667 vol->sectype != ses->sectype)
2668 return 0;
2669
2670 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002671 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002672 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002673 return 0;
2674 break;
2675 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002676 /* NULL username means anonymous session */
2677 if (ses->user_name == NULL) {
2678 if (!vol->nullauth)
2679 return 0;
2680 break;
2681 }
2682
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002683 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002684 if (strncmp(ses->user_name,
2685 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002686 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002687 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002688 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002689 ses->password != NULL &&
2690 strncmp(ses->password,
2691 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002692 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002693 return 0;
2694 }
2695 return 1;
2696}
2697
Aurelien Aptelb327a712018-01-24 13:46:10 +01002698/**
2699 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2700 *
2701 * A new IPC connection is made and stored in the session
2702 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2703 */
2704static int
2705cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2706{
2707 int rc = 0, xid;
2708 struct cifs_tcon *tcon;
2709 struct nls_table *nls_codepage;
2710 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2711 bool seal = false;
2712
2713 /*
2714 * If the mount request that resulted in the creation of the
2715 * session requires encryption, force IPC to be encrypted too.
2716 */
2717 if (volume_info->seal) {
2718 if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
2719 seal = true;
2720 else {
2721 cifs_dbg(VFS,
2722 "IPC: server doesn't support encryption\n");
2723 return -EOPNOTSUPP;
2724 }
2725 }
2726
2727 tcon = tconInfoAlloc();
2728 if (tcon == NULL)
2729 return -ENOMEM;
2730
Thomas Werschlein395a2072018-08-30 18:29:20 +02002731 snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002732
2733 /* cannot fail */
2734 nls_codepage = load_nls_default();
2735
2736 xid = get_xid();
2737 tcon->ses = ses;
2738 tcon->ipc = true;
2739 tcon->seal = seal;
2740 rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
2741 free_xid(xid);
2742
2743 if (rc) {
2744 cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
2745 tconInfoFree(tcon);
2746 goto out;
2747 }
2748
2749 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2750
2751 ses->tcon_ipc = tcon;
2752out:
2753 unload_nls(nls_codepage);
2754 return rc;
2755}
2756
2757/**
2758 * cifs_free_ipc - helper to release the session IPC tcon
2759 *
2760 * Needs to be called everytime a session is destroyed
2761 */
2762static int
2763cifs_free_ipc(struct cifs_ses *ses)
2764{
2765 int rc = 0, xid;
2766 struct cifs_tcon *tcon = ses->tcon_ipc;
2767
2768 if (tcon == NULL)
2769 return 0;
2770
2771 if (ses->server->ops->tree_disconnect) {
2772 xid = get_xid();
2773 rc = ses->server->ops->tree_disconnect(xid, tcon);
2774 free_xid(xid);
2775 }
2776
2777 if (rc)
2778 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
2779
2780 tconInfoFree(tcon);
2781 ses->tcon_ipc = NULL;
2782 return rc;
2783}
2784
Steve French96daf2b2011-05-27 04:34:02 +00002785static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002786cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787{
Steve French96daf2b2011-05-27 04:34:02 +00002788 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302790 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002791 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002792 if (ses->status == CifsExiting)
2793 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002794 if (!match_session(ses, vol))
2795 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002796 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302797 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002798 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302800 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 return NULL;
2802}
2803
Jeff Layton14fbf502008-11-14 13:53:46 -05002804static void
Steve French96daf2b2011-05-27 04:34:02 +00002805cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002806{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002807 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002808 struct TCP_Server_Info *server = ses->server;
2809
Joe Perchesf96637b2013-05-04 22:12:25 -05002810 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002811
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302812 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002813 if (ses->status == CifsExiting) {
2814 spin_unlock(&cifs_tcp_ses_lock);
2815 return;
2816 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002817 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302818 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002819 return;
2820 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002821 if (ses->status == CifsGood)
2822 ses->status = CifsExiting;
2823 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002824
Aurelien Aptelb327a712018-01-24 13:46:10 +01002825 cifs_free_ipc(ses);
2826
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002827 if (ses->status == CifsExiting && server->ops->logoff) {
2828 xid = get_xid();
2829 rc = server->ops->logoff(xid, ses);
2830 if (rc)
2831 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2832 __func__, rc);
2833 _free_xid(xid);
2834 }
2835
2836 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002837 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302838 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002839
Jeff Layton14fbf502008-11-14 13:53:46 -05002840 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002841 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05002842}
2843
Jeff Layton8a8798a2012-01-17 16:09:15 -05002844#ifdef CONFIG_KEYS
2845
Chen Gang057d6332013-07-19 09:01:36 +08002846/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2847#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002848
2849/* Populate username and pw fields from keyring if possible */
2850static int
2851cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2852{
2853 int rc = 0;
David Howells146aa8b2015-10-21 14:04:48 +01002854 const char *delim, *payload;
2855 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002856 ssize_t len;
2857 struct key *key;
2858 struct TCP_Server_Info *server = ses->server;
2859 struct sockaddr_in *sa;
2860 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01002861 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002862
2863 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2864 if (!desc)
2865 return -ENOMEM;
2866
2867 /* try to find an address key first */
2868 switch (server->dstaddr.ss_family) {
2869 case AF_INET:
2870 sa = (struct sockaddr_in *)&server->dstaddr;
2871 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2872 break;
2873 case AF_INET6:
2874 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2875 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2876 break;
2877 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002878 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2879 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002880 rc = -EINVAL;
2881 goto out_err;
2882 }
2883
Joe Perchesf96637b2013-05-04 22:12:25 -05002884 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002885 key = request_key(&key_type_logon, desc, "");
2886 if (IS_ERR(key)) {
2887 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002888 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002889 rc = PTR_ERR(key);
2890 goto out_err;
2891 }
2892
2893 /* didn't work, try to find a domain key */
2894 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002895 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002896 key = request_key(&key_type_logon, desc, "");
2897 if (IS_ERR(key)) {
2898 rc = PTR_ERR(key);
2899 goto out_err;
2900 }
2901 }
2902
2903 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00002904 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002905 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002906 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002907 goto out_key_put;
2908 }
2909
2910 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01002911 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002912 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002913 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002914 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002915 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2916 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002917 rc = -EINVAL;
2918 goto out_key_put;
2919 }
2920
2921 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002922 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002923 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2924 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002925 rc = -EINVAL;
2926 goto out_key_put;
2927 }
2928
2929 vol->username = kstrndup(payload, len, GFP_KERNEL);
2930 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002931 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2932 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002933 rc = -ENOMEM;
2934 goto out_key_put;
2935 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002936 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002937
2938 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002939 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002940 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002941 rc = -EINVAL;
2942 kfree(vol->username);
2943 vol->username = NULL;
2944 goto out_key_put;
2945 }
2946
2947 ++delim;
2948 vol->password = kstrndup(delim, len, GFP_KERNEL);
2949 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002950 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2951 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002952 rc = -ENOMEM;
2953 kfree(vol->username);
2954 vol->username = NULL;
2955 goto out_key_put;
2956 }
2957
2958out_key_put:
2959 up_read(&key->sem);
2960 key_put(key);
2961out_err:
2962 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002963 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002964 return rc;
2965}
2966#else /* ! CONFIG_KEYS */
2967static inline int
2968cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2969 struct cifs_ses *ses __attribute__((unused)))
2970{
2971 return -ENOSYS;
2972}
2973#endif /* CONFIG_KEYS */
2974
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002975/**
2976 * cifs_get_smb_ses - get a session matching @volume_info data from @server
2977 *
2978 * This function assumes it is being called from cifs_mount() where we
2979 * already got a server reference (server refcount +1). See
2980 * cifs_get_tcon() for refcount explanations.
2981 */
Steve French96daf2b2011-05-27 04:34:02 +00002982static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002983cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2984{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002985 int rc = -ENOMEM;
2986 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002987 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002988 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2989 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002990
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002991 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002992
Jeff Layton4ff67b72010-07-06 20:43:02 -04002993 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002994 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002995 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2996 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002997
Jeff Layton36988c72010-04-24 07:57:43 -04002998 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002999 rc = cifs_negotiate_protocol(xid, ses);
3000 if (rc) {
3001 mutex_unlock(&ses->session_mutex);
3002 /* problem -- put our ses reference */
3003 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003004 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003005 return ERR_PTR(rc);
3006 }
Jeff Layton36988c72010-04-24 07:57:43 -04003007 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003008 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003009 rc = cifs_setup_session(xid, ses,
3010 volume_info->local_nls);
3011 if (rc) {
3012 mutex_unlock(&ses->session_mutex);
3013 /* problem -- put our reference */
3014 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003015 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003016 return ERR_PTR(rc);
3017 }
3018 }
3019 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003020
3021 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003022 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003023 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003024 return ses;
3025 }
3026
Joe Perchesf96637b2013-05-04 22:12:25 -05003027 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003028 ses = sesInfoAlloc();
3029 if (ses == NULL)
3030 goto get_ses_fail;
3031
3032 /* new SMB session uses our server ref */
3033 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003034 if (server->dstaddr.ss_family == AF_INET6)
3035 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003036 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003037 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003038
Steve French8727c8a2011-02-25 01:11:56 -06003039 if (volume_info->username) {
3040 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3041 if (!ses->user_name)
3042 goto get_ses_fail;
3043 }
Jeff Layton36988c72010-04-24 07:57:43 -04003044
3045 /* volume_info->password freed at unmount */
3046 if (volume_info->password) {
3047 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3048 if (!ses->password)
3049 goto get_ses_fail;
3050 }
3051 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003052 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3053 if (!ses->domainName)
3054 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003055 }
Germano Percossi39566442016-12-15 12:31:18 +05303056 if (volume_info->domainauto)
3057 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003058 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003059 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003060
Jeff Layton28e11bd2013-05-26 07:01:00 -04003061 ses->sectype = volume_info->sectype;
3062 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003063
3064 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003065 rc = cifs_negotiate_protocol(xid, ses);
3066 if (!rc)
3067 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04003068 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003069 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003070 goto get_ses_fail;
3071
3072 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303073 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003074 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303075 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003076
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003077 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003078
3079 cifs_setup_ipc(ses, volume_info);
3080
Jeff Layton36988c72010-04-24 07:57:43 -04003081 return ses;
3082
3083get_ses_fail:
3084 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003085 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003086 return ERR_PTR(rc);
3087}
3088
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003089static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003090{
3091 if (tcon->tidStatus == CifsExiting)
3092 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003093 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003094 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003095 if (tcon->seal != volume_info->seal)
3096 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003097 if (tcon->snapshot_time != volume_info->snapshot_time)
3098 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003099 return 1;
3100}
3101
Steve French96daf2b2011-05-27 04:34:02 +00003102static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003103cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104{
3105 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003106 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303108 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003109 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003110 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003111 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003112 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003113 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303114 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115 return tcon;
3116 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303117 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 return NULL;
3119}
3120
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003121void
Steve French96daf2b2011-05-27 04:34:02 +00003122cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003123{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003124 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003125 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003126
Aurelien Aptelb327a712018-01-24 13:46:10 +01003127 /*
3128 * IPC tcon share the lifetime of their session and are
3129 * destroyed in the session put function
3130 */
3131 if (tcon == NULL || tcon->ipc)
3132 return;
3133
3134 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003135 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303136 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003137 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303138 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003139 return;
3140 }
3141
3142 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303143 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003144
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003145 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003146 if (ses->server->ops->tree_disconnect)
3147 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003148 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003149
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303150 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003151 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003152 cifs_put_smb_ses(ses);
3153}
3154
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003155/**
3156 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3157 *
3158 * - tcon refcount is the number of mount points using the tcon.
3159 * - ses refcount is the number of tcon using the session.
3160 *
3161 * 1. This function assumes it is being called from cifs_mount() where
3162 * we already got a session reference (ses refcount +1).
3163 *
3164 * 2. Since we're in the context of adding a mount point, the end
3165 * result should be either:
3166 *
3167 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3168 * its session refcount incremented (1 new tcon). This +1 was
3169 * already done in (1).
3170 *
3171 * b) an existing tcon with refcount+1 (add a mount point to it) and
3172 * identical ses refcount (no new tcon). Because of (1) we need to
3173 * decrement the ses refcount.
3174 */
Steve French96daf2b2011-05-27 04:34:02 +00003175static struct cifs_tcon *
3176cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003177{
3178 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003179 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003180
Steve French8b217fe2016-11-11 22:36:20 -06003181 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003182 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003183 /*
3184 * tcon has refcount already incremented but we need to
3185 * decrement extra ses reference gotten by caller (case b)
3186 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003187 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003188 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003189 return tcon;
3190 }
3191
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003192 if (!ses->server->ops->tree_connect) {
3193 rc = -ENOSYS;
3194 goto out_fail;
3195 }
3196
Jeff Laytond00c28d2010-04-24 07:57:44 -04003197 tcon = tconInfoAlloc();
3198 if (tcon == NULL) {
3199 rc = -ENOMEM;
3200 goto out_fail;
3201 }
3202
Steve French8b217fe2016-11-11 22:36:20 -06003203 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003204 if (ses->server->vals->protocol_id == 0) {
3205 cifs_dbg(VFS,
3206 "Use SMB2 or later for snapshot mount option\n");
3207 rc = -EOPNOTSUPP;
3208 goto out_fail;
3209 } else
3210 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003211 }
3212
Jeff Laytond00c28d2010-04-24 07:57:44 -04003213 tcon->ses = ses;
3214 if (volume_info->password) {
3215 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3216 if (!tcon->password) {
3217 rc = -ENOMEM;
3218 goto out_fail;
3219 }
3220 }
3221
Steve French23657ad2018-04-22 15:14:58 -05003222 if (volume_info->seal) {
3223 if (ses->server->vals->protocol_id == 0) {
3224 cifs_dbg(VFS,
3225 "SMB3 or later required for encryption\n");
3226 rc = -EOPNOTSUPP;
3227 goto out_fail;
3228 } else if (tcon->ses->server->capabilities &
3229 SMB2_GLOBAL_CAP_ENCRYPTION)
3230 tcon->seal = true;
3231 else {
3232 cifs_dbg(VFS, "Encryption is not supported on share\n");
3233 rc = -EOPNOTSUPP;
3234 goto out_fail;
3235 }
3236 }
3237
Steve French8505c8b2018-06-18 14:01:59 -05003238 if (volume_info->linux_ext) {
3239 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003240 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003241 printk_once(KERN_WARNING
3242 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003243 } else {
3244 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3245 rc = -EOPNOTSUPP;
3246 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003247 }
Steve Frenchb3266142018-05-20 23:41:10 -05003248 }
Steve Frenchb3266142018-05-20 23:41:10 -05003249
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003250 /*
3251 * BB Do we need to wrap session_mutex around this TCon call and Unix
3252 * SetFS as we do on SessSetup and reconnect?
3253 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003254 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003255 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3256 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003257 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003258 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003259 if (rc)
3260 goto out_fail;
3261
Steve Frenchb618f002015-11-03 09:15:03 -06003262 tcon->use_persistent = false;
3263 /* check if SMB2 or later, CIFS does not support persistent handles */
3264 if (volume_info->persistent) {
3265 if (ses->server->vals->protocol_id == 0) {
3266 cifs_dbg(VFS,
3267 "SMB3 or later required for persistent handles\n");
3268 rc = -EOPNOTSUPP;
3269 goto out_fail;
3270 } else if (ses->server->capabilities &
3271 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3272 tcon->use_persistent = true;
3273 else /* persistent handles requested but not supported */ {
3274 cifs_dbg(VFS,
3275 "Persistent handles not supported on share\n");
3276 rc = -EOPNOTSUPP;
3277 goto out_fail;
3278 }
3279 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3280 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3281 && (volume_info->nopersistent == false)) {
3282 cifs_dbg(FYI, "enabling persistent handles\n");
3283 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003284 } else if (volume_info->resilient) {
3285 if (ses->server->vals->protocol_id == 0) {
3286 cifs_dbg(VFS,
3287 "SMB2.1 or later required for resilient handles\n");
3288 rc = -EOPNOTSUPP;
3289 goto out_fail;
3290 }
3291 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003292 }
3293
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003294 /*
3295 * We can have only one retry value for a connection to a share so for
3296 * resources mounted more than once to the same server share the last
3297 * value passed in for the retry flag is used.
3298 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003299 tcon->retry = volume_info->retry;
3300 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003301 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003302 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003303 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003304
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303305 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003306 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303307 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003308
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303309 cifs_fscache_get_super_cookie(tcon);
3310
Jeff Laytond00c28d2010-04-24 07:57:44 -04003311 return tcon;
3312
3313out_fail:
3314 tconInfoFree(tcon);
3315 return ERR_PTR(rc);
3316}
3317
Jeff Layton9d002df2010-10-06 19:51:11 -04003318void
3319cifs_put_tlink(struct tcon_link *tlink)
3320{
3321 if (!tlink || IS_ERR(tlink))
3322 return;
3323
3324 if (!atomic_dec_and_test(&tlink->tl_count) ||
3325 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3326 tlink->tl_time = jiffies;
3327 return;
3328 }
3329
3330 if (!IS_ERR(tlink_tcon(tlink)))
3331 cifs_put_tcon(tlink_tcon(tlink));
3332 kfree(tlink);
3333 return;
3334}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003335
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003336static int
3337compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3338{
3339 struct cifs_sb_info *old = CIFS_SB(sb);
3340 struct cifs_sb_info *new = mnt_data->cifs_sb;
3341
3342 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3343 return 0;
3344
3345 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
3346 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
3347 return 0;
3348
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003349 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003350 * We want to share sb only if we don't specify an r/wsize or
3351 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003352 */
3353 if (new->wsize && new->wsize < old->wsize)
3354 return 0;
3355
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003356 if (new->rsize && new->rsize < old->rsize)
3357 return 0;
3358
Eric W. Biederman1f682332013-02-06 01:20:20 -08003359 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003360 return 0;
3361
3362 if (old->mnt_file_mode != new->mnt_file_mode ||
3363 old->mnt_dir_mode != new->mnt_dir_mode)
3364 return 0;
3365
3366 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3367 return 0;
3368
3369 if (old->actimeo != new->actimeo)
3370 return 0;
3371
3372 return 1;
3373}
3374
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003375static int
3376match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3377{
3378 struct cifs_sb_info *old = CIFS_SB(sb);
3379 struct cifs_sb_info *new = mnt_data->cifs_sb;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003380 bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3381 bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003382
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003383 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003384 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003385 else if (!old_set && !new_set)
3386 return 1;
3387
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003388 return 0;
3389}
3390
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003391int
3392cifs_match_super(struct super_block *sb, void *data)
3393{
3394 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3395 struct smb_vol *volume_info;
3396 struct cifs_sb_info *cifs_sb;
3397 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003398 struct cifs_ses *ses;
3399 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003400 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003401 int rc = 0;
3402
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003403 spin_lock(&cifs_tcp_ses_lock);
3404 cifs_sb = CIFS_SB(sb);
3405 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3406 if (IS_ERR(tlink)) {
3407 spin_unlock(&cifs_tcp_ses_lock);
3408 return rc;
3409 }
3410 tcon = tlink_tcon(tlink);
3411 ses = tcon->ses;
3412 tcp_srv = ses->server;
3413
3414 volume_info = mnt_data->vol;
3415
Jeff Layton9fa114f2012-11-26 11:09:57 -05003416 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003417 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003418 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003419 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003420 rc = 0;
3421 goto out;
3422 }
3423
3424 rc = compare_mount_options(sb, mnt_data);
3425out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003426 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003427 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003428 return rc;
3429}
3430
Jeff Layton09e50d52008-07-23 10:11:19 -04003431#ifdef CONFIG_DEBUG_LOCK_ALLOC
3432static struct lock_class_key cifs_key[2];
3433static struct lock_class_key cifs_slock_key[2];
3434
3435static inline void
3436cifs_reclassify_socket4(struct socket *sock)
3437{
3438 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003439 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003440 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3441 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3442}
3443
3444static inline void
3445cifs_reclassify_socket6(struct socket *sock)
3446{
3447 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003448 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003449 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3450 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3451}
3452#else
3453static inline void
3454cifs_reclassify_socket4(struct socket *sock)
3455{
3456}
3457
3458static inline void
3459cifs_reclassify_socket6(struct socket *sock)
3460{
3461}
3462#endif
3463
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003465static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466{
Steve French50c2f752007-07-13 00:33:32 +00003467 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468
Steve French50c2f752007-07-13 00:33:32 +00003469 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470 /* mask a nibble at a time and encode */
3471 target[j] = 'A' + (0x0F & (source[i] >> 4));
3472 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003473 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474 }
3475
3476}
3477
Ben Greear3eb9a882010-09-01 17:06:02 -07003478static int
3479bind_socket(struct TCP_Server_Info *server)
3480{
3481 int rc = 0;
3482 if (server->srcaddr.ss_family != AF_UNSPEC) {
3483 /* Bind to the specified local IP address */
3484 struct socket *socket = server->ssocket;
3485 rc = socket->ops->bind(socket,
3486 (struct sockaddr *) &server->srcaddr,
3487 sizeof(server->srcaddr));
3488 if (rc < 0) {
3489 struct sockaddr_in *saddr4;
3490 struct sockaddr_in6 *saddr6;
3491 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3492 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3493 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05003494 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3495 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003496 else
Joe Perchesf96637b2013-05-04 22:12:25 -05003497 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3498 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003499 }
3500 }
3501 return rc;
3502}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503
3504static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003505ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506{
3507 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003508 /*
3509 * some servers require RFC1001 sessinit before sending
3510 * negprot - BB check reconnection in case where second
3511 * sessinit is sent but no second negprot
3512 */
3513 struct rfc1002_session_packet *ses_init_buf;
3514 struct smb_hdr *smb_buf;
3515 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3516 GFP_KERNEL);
3517 if (ses_init_buf) {
3518 ses_init_buf->trailer.session_req.called_len = 32;
3519
Colin Ian King997152f2016-01-25 16:25:54 +00003520 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003521 rfc1002mangle(ses_init_buf->trailer.
3522 session_req.called_name,
3523 server->server_RFC1001_name,
3524 RFC1001_NAME_LEN_WITH_NULL);
3525 else
3526 rfc1002mangle(ses_init_buf->trailer.
3527 session_req.called_name,
3528 DEFAULT_CIFS_CALLED_NAME,
3529 RFC1001_NAME_LEN_WITH_NULL);
3530
3531 ses_init_buf->trailer.session_req.calling_len = 32;
3532
3533 /*
3534 * calling name ends in null (byte 16) from old smb
3535 * convention.
3536 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003537 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003538 rfc1002mangle(ses_init_buf->trailer.
3539 session_req.calling_name,
3540 server->workstation_RFC1001_name,
3541 RFC1001_NAME_LEN_WITH_NULL);
3542 else
3543 rfc1002mangle(ses_init_buf->trailer.
3544 session_req.calling_name,
3545 "LINUX_CIFS_CLNT",
3546 RFC1001_NAME_LEN_WITH_NULL);
3547
3548 ses_init_buf->trailer.session_req.scope1 = 0;
3549 ses_init_buf->trailer.session_req.scope2 = 0;
3550 smb_buf = (struct smb_hdr *)ses_init_buf;
3551
3552 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003553 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003554 rc = smb_send(server, smb_buf, 0x44);
3555 kfree(ses_init_buf);
3556 /*
3557 * RFC1001 layer in at least one server
3558 * requires very short break before negprot
3559 * presumably because not expecting negprot
3560 * to follow so fast. This is a simple
3561 * solution that works without
3562 * complicating the code and causes no
3563 * significant slowing down on mount
3564 * for everyone else
3565 */
3566 usleep_range(1000, 2000);
3567 }
3568 /*
3569 * else the negprot may still work without this
3570 * even though malloc failed
3571 */
3572
3573 return rc;
3574}
3575
3576static int
3577generic_ip_connect(struct TCP_Server_Info *server)
3578{
3579 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003580 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003581 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003582 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003583 struct sockaddr *saddr;
3584
3585 saddr = (struct sockaddr *) &server->dstaddr;
3586
3587 if (server->dstaddr.ss_family == AF_INET6) {
3588 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3589 slen = sizeof(struct sockaddr_in6);
3590 sfamily = AF_INET6;
3591 } else {
3592 sport = ((struct sockaddr_in *) saddr)->sin_port;
3593 slen = sizeof(struct sockaddr_in);
3594 sfamily = AF_INET;
3595 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003597 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003598 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3599 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003601 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003602 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003605
3606 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003607 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003608 server->ssocket = socket;
3609 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003610 if (sfamily == AF_INET6)
3611 cifs_reclassify_socket6(socket);
3612 else
3613 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 }
3615
Ben Greear3eb9a882010-09-01 17:06:02 -07003616 rc = bind_socket(server);
3617 if (rc < 0)
3618 return rc;
3619
Jeff Laytond5c56052008-12-01 18:42:33 -05003620 /*
3621 * Eventually check for other socket options to change from
3622 * the default. sock_setsockopt not used because it expects
3623 * user space buffer
3624 */
3625 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003626 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003627
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003628 /* make the bufsizes depend on wsize/rsize and max requests */
3629 if (server->noautotune) {
3630 if (socket->sk->sk_sndbuf < (200 * 1024))
3631 socket->sk->sk_sndbuf = 200 * 1024;
3632 if (socket->sk->sk_rcvbuf < (140 * 1024))
3633 socket->sk->sk_rcvbuf = 140 * 1024;
3634 }
3635
Steve French6a5fa2362010-01-01 01:28:43 +00003636 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003637 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003638 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3639 (char *)&val, sizeof(val));
3640 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003641 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3642 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003643 }
3644
Joe Perchesf96637b2013-05-04 22:12:25 -05003645 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003646 socket->sk->sk_sndbuf,
3647 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3648
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003649 rc = socket->ops->connect(socket, saddr, slen, 0);
3650 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003651 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003652 sock_release(socket);
3653 server->ssocket = NULL;
3654 return rc;
3655 }
3656
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003657 if (sport == htons(RFC1001_PORT))
3658 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003659
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 return rc;
3661}
3662
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003663static int
3664ip_connect(struct TCP_Server_Info *server)
3665{
Steve French6da97912011-03-13 18:55:55 +00003666 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003667 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3668 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3669
3670 if (server->dstaddr.ss_family == AF_INET6)
3671 sport = &addr6->sin6_port;
3672 else
3673 sport = &addr->sin_port;
3674
3675 if (*sport == 0) {
3676 int rc;
3677
3678 /* try with 445 port at first */
3679 *sport = htons(CIFS_PORT);
3680
3681 rc = generic_ip_connect(server);
3682 if (rc >= 0)
3683 return rc;
3684
3685 /* if it failed, try with 139 port */
3686 *sport = htons(RFC1001_PORT);
3687 }
3688
3689 return generic_ip_connect(server);
3690}
3691
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003692void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003693 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003694{
3695 /* if we are reconnecting then should we check to see if
3696 * any requested capabilities changed locally e.g. via
3697 * remount but we can not do much about it here
3698 * if they have (even if we could detect it by the following)
3699 * Perhaps we could add a backpointer to array of sb from tcon
3700 * or if we change to make all sb to same share the same
3701 * sb as NFS - then we only have one backpointer to sb.
3702 * What if we wanted to mount the server share twice once with
3703 * and once without posixacls or posix paths? */
3704 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003705
Steve Frenchc18c8422007-07-18 23:21:09 +00003706 if (vol_info && vol_info->no_linux_ext) {
3707 tcon->fsUnixInfo.Capability = 0;
3708 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003709 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003710 return;
3711 } else if (vol_info)
3712 tcon->unix_ext = 1; /* Unix Extensions supported */
3713
3714 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003715 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003716 return;
3717 }
Steve French50c2f752007-07-13 00:33:32 +00003718
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003719 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003720 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003721 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003722 /* check for reconnect case in which we do not
3723 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003724 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003725 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003726 originally at mount time */
3727 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3728 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003729 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3730 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003731 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003732 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003733 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003734 cifs_dbg(VFS, "possible reconnect error\n");
3735 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003736 }
Steve French8af18972007-02-14 04:42:51 +00003737 }
Steve French50c2f752007-07-13 00:33:32 +00003738
Steve French6848b732011-05-26 18:38:54 +00003739 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003740 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003741
Steve French8af18972007-02-14 04:42:51 +00003742 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003743 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003744 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003745 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003746 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003747 if (cifs_sb)
3748 cifs_sb->mnt_cifs_flags |=
3749 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003750 }
3751
Steve French75865f8c2007-06-24 18:30:48 +00003752 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003753 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003754 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003755 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003756 if (cifs_sb)
3757 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003758 CIFS_MOUNT_POSIX_PATHS;
3759 }
Steve French50c2f752007-07-13 00:33:32 +00003760
Joe Perchesf96637b2013-05-04 22:12:25 -05003761 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003762#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003763 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003764 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003765 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003766 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003767 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003768 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003769 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003770 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003771 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003772 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003773 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003774 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003775 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003776 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003777 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003778 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003779 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003780 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003781#endif /* CIFS_DEBUG2 */
3782 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003783 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003784 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003785 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003786 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 +00003787
Steve French8af18972007-02-14 04:42:51 +00003788 }
3789 }
3790}
3791
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003792int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003793 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003794{
Jeff Layton2de970f2010-10-06 19:51:12 -04003795 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3796
Al Viro2ced6f62011-06-17 09:20:04 -04003797 spin_lock_init(&cifs_sb->tlink_tree_lock);
3798 cifs_sb->tlink_tree = RB_ROOT;
3799
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003800 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003801 * Temporarily set r/wsize for matching superblock. If we end up using
3802 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003803 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003804 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003805 cifs_sb->wsize = pvolume_info->wsize;
3806
Steve French3b795212008-11-13 19:45:32 +00003807 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3808 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3809 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3810 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003811 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3812 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003813
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303814 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003815 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303816
Aurelien Aptel83930722018-09-20 18:10:25 -07003817 if (pvolume_info->nodfs)
3818 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00003819 if (pvolume_info->noperm)
3820 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3821 if (pvolume_info->setuids)
3822 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05003823 if (pvolume_info->setuidfromacl)
3824 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00003825 if (pvolume_info->server_ino)
3826 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3827 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003828 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3829 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003830 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3831 if (pvolume_info->no_xattr)
3832 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3833 if (pvolume_info->sfu_emul)
3834 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3835 if (pvolume_info->nobrl)
3836 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05003837 if (pvolume_info->nohandlecache)
3838 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00003839 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003840 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003841 if (pvolume_info->mand_lock)
3842 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003843 if (pvolume_info->rwpidforward)
3844 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003845 if (pvolume_info->cifs_acl)
3846 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003847 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003848 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003849 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3850 }
3851 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003852 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003853 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3854 }
Steve French3b795212008-11-13 19:45:32 +00003855 if (pvolume_info->override_uid)
3856 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3857 if (pvolume_info->override_gid)
3858 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3859 if (pvolume_info->dynperm)
3860 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303861 if (pvolume_info->fsc)
3862 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003863 if (pvolume_info->multiuser)
3864 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3865 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003866 if (pvolume_info->strict_io)
3867 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003868 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003869 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003870 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3871 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003872 if (pvolume_info->mfsymlinks) {
3873 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003874 /*
3875 * Our SFU ("Services for Unix" emulation does not allow
3876 * creating symlinks but does allow reading existing SFU
3877 * symlinks (it does allow both creating and reading SFU
3878 * style mknod and FIFOs though). When "mfsymlinks" and
3879 * "sfu" are both enabled at the same time, it allows
3880 * reading both types of symlinks, but will only create
3881 * them with mfsymlinks format. This allows better
3882 * Apple compatibility (probably better for Samba too)
3883 * while still recognizing old Windows style symlinks.
3884 */
3885 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003886 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003887 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003888 }
Steve French3b795212008-11-13 19:45:32 +00003889
3890 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003891 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003892
3893 if (pvolume_info->prepath) {
3894 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
3895 if (cifs_sb->prepath == NULL)
3896 return -ENOMEM;
3897 }
3898
3899 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003900}
3901
Paulo Alcantara56c762e2018-11-14 13:03:14 -02003902void
3903cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003904{
Sean Finneyb9468452011-04-11 13:19:32 +00003905 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003906 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003907 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003908 kfree(volume_info->domainname);
3909 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003910 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003911}
3912
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003913void
3914cifs_cleanup_volume_info(struct smb_vol *volume_info)
3915{
3916 if (!volume_info)
3917 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02003918 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003919 kfree(volume_info);
3920}
3921
Paulo Alcantara56c762e2018-11-14 13:03:14 -02003922/* Release all succeed connections */
3923static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
3924 unsigned int xid,
3925 struct TCP_Server_Info *server,
3926 struct cifs_ses *ses, struct cifs_tcon *tcon)
3927{
3928 int rc = 0;
3929
3930 if (tcon)
3931 cifs_put_tcon(tcon);
3932 else if (ses)
3933 cifs_put_smb_ses(ses);
3934 else if (server)
3935 cifs_put_tcp_session(server, 0);
3936 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
3937 free_xid(xid);
3938}
3939
3940/* Get connections for tcp, ses and tcon */
3941static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
3942 unsigned int *xid,
3943 struct TCP_Server_Info **nserver,
3944 struct cifs_ses **nses, struct cifs_tcon **ntcon)
3945{
3946 int rc = 0;
3947 struct TCP_Server_Info *server;
3948 struct cifs_ses *ses;
3949 struct cifs_tcon *tcon;
3950
3951 *nserver = NULL;
3952 *nses = NULL;
3953 *ntcon = NULL;
3954
3955 *xid = get_xid();
3956
3957 /* get a reference to a tcp session */
3958 server = cifs_get_tcp_session(vol);
3959 if (IS_ERR(server)) {
3960 rc = PTR_ERR(server);
3961 return rc;
3962 }
3963
3964 *nserver = server;
3965
3966 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
3967 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
3968 else
3969 server->max_credits = vol->max_credits;
3970
3971 /* get a reference to a SMB session */
3972 ses = cifs_get_smb_ses(server, vol);
3973 if (IS_ERR(ses)) {
3974 rc = PTR_ERR(ses);
3975 return rc;
3976 }
3977
3978 *nses = ses;
3979
3980 if ((vol->persistent == true) && (!(ses->server->capabilities &
3981 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
3982 cifs_dbg(VFS, "persistent handles not supported by server\n");
3983 return -EOPNOTSUPP;
3984 }
3985
3986 /* search for existing tcon to this server share */
3987 tcon = cifs_get_tcon(ses, vol);
3988 if (IS_ERR(tcon)) {
3989 rc = PTR_ERR(tcon);
3990 return rc;
3991 }
3992
3993 *ntcon = tcon;
3994
3995 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
3996 if (tcon->posix_extensions)
3997 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
3998
3999 /* tell server which Unix caps we support */
4000 if (cap_unix(tcon->ses)) {
4001 /*
4002 * reset of caps checks mount to see if unix extensions disabled
4003 * for just this mount.
4004 */
4005 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4006 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4007 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4008 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4009 return -EACCES;
4010 } else
4011 tcon->unix_ext = 0; /* server does not support them */
4012
4013 /* do not care if a following call succeed - informational */
4014 if (!tcon->pipe && server->ops->qfs_tcon)
4015 server->ops->qfs_tcon(*xid, tcon);
4016
4017 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4018 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4019
4020 return 0;
4021}
4022
4023static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4024 struct cifs_tcon *tcon)
4025{
4026 struct tcon_link *tlink;
4027
4028 /* hang the tcon off of the superblock */
4029 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4030 if (tlink == NULL)
4031 return -ENOMEM;
4032
4033 tlink->tl_uid = ses->linux_uid;
4034 tlink->tl_tcon = tcon;
4035 tlink->tl_time = jiffies;
4036 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4037 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4038
4039 cifs_sb->master_tlink = tlink;
4040 spin_lock(&cifs_sb->tlink_tree_lock);
4041 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4042 spin_unlock(&cifs_sb->tlink_tree_lock);
4043
4044 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4045 TLINK_IDLE_EXPIRE);
4046 return 0;
4047}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004048
Steve French2d6d5892009-04-09 00:36:44 +00004049#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004050/*
4051 * cifs_build_path_to_root returns full path to root when we do not have an
4052 * exiting connection (tcon)
4053 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004054static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004055build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004056 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004057{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004058 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004059 unsigned int pplen = useppath && vol->prepath ?
4060 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004061 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004062
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004063 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004064 if (full_path == NULL)
4065 return ERR_PTR(-ENOMEM);
4066
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004067 strncpy(full_path, vol->UNC, unc_len);
4068 pos = full_path + unc_len;
4069
4070 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004071 *pos = CIFS_DIR_SEP(cifs_sb);
4072 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004073 pos += pplen;
4074 }
4075
4076 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004077 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004078 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004079 return full_path;
4080}
Sean Finneydd613942011-04-11 13:19:30 +00004081
Paulo Alcantara1c780222018-11-14 16:24:03 -02004082/**
4083 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4084 *
Sean Finneydd613942011-04-11 13:19:30 +00004085 *
Sean Finney046462a2011-04-11 13:19:33 +00004086 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4087 * to a string containing updated options for the submount. Otherwise it
4088 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004089 *
4090 * Returns the rc from get_dfs_path to the caller, which can be used to
4091 * determine whether there were referrals.
4092 */
4093static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004094expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004095 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00004096 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00004097{
4098 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004099 struct dfs_info3_param referral = {0};
Sean Finneydd613942011-04-11 13:19:30 +00004100 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4101
Aurelien Aptel83930722018-09-20 18:10:25 -07004102 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4103 return -EREMOTE;
4104
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004105 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004106 if (IS_ERR(full_path))
4107 return PTR_ERR(full_path);
4108
4109 /* For DFS paths, skip the first '\' of the UNC */
4110 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4111
Paulo Alcantara1c780222018-11-14 16:24:03 -02004112 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4113 ref_path, &referral, NULL);
4114 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004115 char *fake_devname = NULL;
4116
4117 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004118 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004119 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004120 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004121
Sean Finneydd613942011-04-11 13:19:30 +00004122 if (IS_ERR(mdata)) {
4123 rc = PTR_ERR(mdata);
4124 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004125 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004126 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004127 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004128 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004129 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004130 kfree(fake_devname);
4131 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004132 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004133 }
4134 kfree(full_path);
4135 return rc;
4136}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004137
4138static inline int get_next_dfs_tgt(const char *path,
4139 struct dfs_cache_tgt_list *tgt_list,
4140 struct dfs_cache_tgt_iterator **tgt_it)
4141{
4142 if (!*tgt_it)
4143 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4144 else
4145 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4146 return !*tgt_it ? -EHOSTDOWN : 0;
4147}
4148
4149static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4150 struct smb_vol *fake_vol, struct smb_vol *vol)
4151{
4152 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4153 int len = strlen(tgt) + 2;
4154 char *new_unc;
4155
4156 new_unc = kmalloc(len, GFP_KERNEL);
4157 if (!new_unc)
4158 return -ENOMEM;
4159 snprintf(new_unc, len, "\\%s", tgt);
4160
4161 kfree(vol->UNC);
4162 vol->UNC = new_unc;
4163
4164 if (fake_vol->prepath) {
4165 kfree(vol->prepath);
4166 vol->prepath = fake_vol->prepath;
4167 fake_vol->prepath = NULL;
4168 }
4169 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4170
4171 return 0;
4172}
4173
4174static int setup_dfs_tgt_conn(const char *path,
4175 const struct dfs_cache_tgt_iterator *tgt_it,
4176 struct cifs_sb_info *cifs_sb,
4177 struct smb_vol *vol,
4178 unsigned int *xid,
4179 struct TCP_Server_Info **server,
4180 struct cifs_ses **ses,
4181 struct cifs_tcon **tcon)
4182{
4183 int rc;
4184 struct dfs_info3_param ref = {0};
4185 char *mdata = NULL, *fake_devname = NULL;
4186 struct smb_vol fake_vol = {0};
4187
4188 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4189
4190 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4191 if (rc)
4192 return rc;
4193
4194 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4195 &fake_devname);
4196 free_dfs_info_param(&ref);
4197
4198 if (IS_ERR(mdata)) {
4199 rc = PTR_ERR(mdata);
4200 mdata = NULL;
4201 } else {
4202 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4203 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4204 false);
4205 }
4206 kfree(mdata);
4207 kfree(fake_devname);
4208
4209 if (!rc) {
4210 /*
4211 * We use a 'fake_vol' here because we need pass it down to the
4212 * mount_{get,put} functions to test connection against new DFS
4213 * targets.
4214 */
4215 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4216 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4217 tcon);
4218 if (!rc) {
4219 /*
4220 * We were able to connect to new target server.
4221 * Update current volume info with new target server.
4222 */
4223 rc = update_vol_info(tgt_it, &fake_vol, vol);
4224 }
4225 }
4226 cifs_cleanup_volume_info_contents(&fake_vol);
4227 return rc;
4228}
4229
4230static int mount_do_dfs_failover(const char *path,
4231 struct cifs_sb_info *cifs_sb,
4232 struct smb_vol *vol,
4233 struct cifs_ses *root_ses,
4234 unsigned int *xid,
4235 struct TCP_Server_Info **server,
4236 struct cifs_ses **ses,
4237 struct cifs_tcon **tcon)
4238{
4239 int rc;
4240 struct dfs_cache_tgt_list tgt_list;
4241 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4242
4243 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4244 return -EOPNOTSUPP;
4245
4246 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4247 if (rc)
4248 return rc;
4249
4250 for (;;) {
4251 /* Get next DFS target server - if any */
4252 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4253 if (rc)
4254 break;
4255 /* Connect to next DFS target */
4256 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4257 ses, tcon);
4258 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4259 break;
4260 }
4261 if (!rc) {
4262 /*
4263 * Update DFS target hint in DFS referral cache with the target
4264 * server we successfully reconnected to.
4265 */
4266 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4267 cifs_sb->local_nls,
4268 cifs_remap(cifs_sb), path,
4269 tgt_it);
4270 }
4271 dfs_cache_free_tgts(&tgt_list);
4272 return rc;
4273}
Steve French2d6d5892009-04-09 00:36:44 +00004274#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004275
Jeff Layton04db79b2011-07-06 08:10:38 -04004276static int
4277cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004278 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004280 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004281
Steve Frenchc7c137b2018-06-06 17:59:29 -05004282 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004283 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284
Jeff Layton7586b762008-12-01 18:41:49 -05004285 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004286 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004287 kfree(volume_info->username);
4288 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004289 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004291 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004293 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004294 /* In userspace mount helper we can get user name from alternate
4295 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004296 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 }
4298
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004300 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004301 /* load_nls_default cannot return null */
4302 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004304 volume_info->local_nls = load_nls(volume_info->iocharset);
4305 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004306 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004307 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004308 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 }
4310 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004311
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004312 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004313}
4314
4315struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004316cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004317{
4318 int rc;
4319 struct smb_vol *volume_info;
4320
Jeff Layton6ee95422012-11-26 11:09:57 -05004321 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004322 if (!volume_info)
4323 return ERR_PTR(-ENOMEM);
4324
Steve Frenchc7c137b2018-06-06 17:59:29 -05004325 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004326 if (rc) {
4327 cifs_cleanup_volume_info(volume_info);
4328 volume_info = ERR_PTR(rc);
4329 }
4330
4331 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004332}
4333
Aurelien Aptela6b50582016-05-25 19:59:09 +02004334static int
4335cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4336 unsigned int xid,
4337 struct cifs_tcon *tcon,
4338 struct cifs_sb_info *cifs_sb,
4339 char *full_path)
4340{
4341 int rc;
4342 char *s;
4343 char sep, tmp;
4344
4345 sep = CIFS_DIR_SEP(cifs_sb);
4346 s = full_path;
4347
4348 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4349 while (rc == 0) {
4350 /* skip separators */
4351 while (*s == sep)
4352 s++;
4353 if (!*s)
4354 break;
4355 /* next separator */
4356 while (*s && *s != sep)
4357 s++;
4358
4359 /*
4360 * temporarily null-terminate the path at the end of
4361 * the current component
4362 */
4363 tmp = *s;
4364 *s = 0;
4365 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4366 full_path);
4367 *s = tmp;
4368 }
4369 return rc;
4370}
4371
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004372/*
4373 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4374 * otherwise 0.
4375 */
4376static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4377 const unsigned int xid,
4378 struct TCP_Server_Info *server,
4379 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004380{
Jeff Layton1daaae82012-03-21 06:30:40 -04004381 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004382 char *full_path;
4383
4384 if (!server->ops->is_path_accessible)
4385 return -EOPNOTSUPP;
4386
4387 /*
4388 * cifs_build_path_to_root works only when we have a valid tcon
4389 */
4390 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4391 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4392 if (full_path == NULL)
4393 return -ENOMEM;
4394
4395 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4396
4397 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4398 full_path);
4399 if (rc != 0 && rc != -EREMOTE) {
4400 kfree(full_path);
4401 return rc;
4402 }
4403
4404 if (rc != -EREMOTE) {
4405 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
4406 cifs_sb,
4407 full_path);
4408 if (rc != 0) {
4409 cifs_dbg(VFS, "cannot query dirs between root and final path, "
4410 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4411 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4412 rc = 0;
4413 }
4414 }
4415
4416 kfree(full_path);
4417 return rc;
4418}
4419
4420#ifdef CONFIG_CIFS_DFS_UPCALL
4421int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4422{
4423 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004424 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004425 struct cifs_ses *ses;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004426 struct cifs_tcon *root_tcon = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004427 struct cifs_tcon *tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004428 struct TCP_Server_Info *server;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004429 char *root_path = NULL, *full_path = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004430 char *old_mountdata;
4431 int count;
Al Virodd854462011-06-17 08:24:42 -04004432
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004433 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4434 if (!rc && tcon) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004435 /* If not a standalone DFS root, then check if path is remote */
4436 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4437 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4438 NULL);
4439 if (rc) {
4440 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4441 if (!rc)
4442 goto out;
4443 if (rc != -EREMOTE)
4444 goto error;
4445 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004446 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004447 /*
4448 * If first DFS target server went offline and we failed to connect it,
4449 * server and ses pointers are NULL at this point, though we still have
4450 * chance to get a cached DFS referral in expand_dfs_referral() and
4451 * retry next target available in it.
4452 *
4453 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4454 * performed against DFS path and *no* requests will be sent to server
4455 * for any new DFS referrals. Hence it's safe to skip checking whether
4456 * server or ses ptr is NULL.
4457 */
4458 if (rc == -EACCES || rc == -EOPNOTSUPP)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004459 goto error;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004460
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004461 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4462 if (IS_ERR(root_path)) {
4463 rc = PTR_ERR(root_path);
4464 root_path = NULL;
4465 goto error;
4466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004468 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4469 if (IS_ERR(full_path)) {
4470 rc = PTR_ERR(full_path);
4471 full_path = NULL;
4472 goto error;
4473 }
Sean Finneyc1508ca2011-04-11 13:19:31 +00004474 /*
4475 * Perform an unconditional check for whether there are DFS
4476 * referrals for this path without prefix, to provide support
4477 * for DFS referrals from w2k8 servers which don't seem to respond
4478 * with PATH_NOT_COVERED to requests that include the prefix.
4479 * Chase the referral if found, otherwise continue normally.
4480 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004481 old_mountdata = cifs_sb->mountdata;
4482 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004483
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004484 if (cifs_sb->mountdata == NULL) {
4485 rc = -ENOENT;
4486 goto error;
4487 }
4488
4489 if (cifs_sb->mountdata != old_mountdata) {
4490 /* If we were redirected, reconnect to new target server */
4491 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4492 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4493 }
4494 if (rc) {
4495 if (rc == -EACCES || rc == -EOPNOTSUPP)
4496 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004497 /* Perform DFS failover to any other DFS targets */
4498 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4499 &xid, &server, &ses, &tcon);
4500 if (rc)
4501 goto error;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004502 }
4503
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004504 kfree(root_path);
4505 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4506 if (IS_ERR(root_path)) {
4507 rc = PTR_ERR(root_path);
4508 root_path = NULL;
4509 goto error;
4510 }
4511 /* Cache out resolved root server */
4512 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4513 root_path + 1, NULL, NULL);
4514 /*
4515 * Save root tcon for additional DFS requests to update or create a new
4516 * DFS cache entry, or even perform DFS failover.
4517 */
4518 spin_lock(&cifs_tcp_ses_lock);
4519 tcon->tc_count++;
4520 tcon->dfs_path = root_path;
4521 root_path = NULL;
4522 tcon->remap = cifs_remap(cifs_sb);
4523 spin_unlock(&cifs_tcp_ses_lock);
4524
4525 root_tcon = tcon;
4526
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004527 for (count = 1; ;) {
4528 if (!rc && tcon) {
4529 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4530 if (!rc || rc != -EREMOTE)
4531 break;
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004532 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004533 /*
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004534 * BB: when we implement proper loop detection,
4535 * we will remove this check. But now we need it
4536 * to prevent an indefinite loop if 'DFS tree' is
4537 * misconfigured (i.e. has loops).
Steve French6d3ea7e2012-11-28 22:34:41 -06004538 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004539 if (count++ > MAX_NESTED_LINKS) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004540 rc = -ELOOP;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004541 break;
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004542 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004543
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004544 kfree(full_path);
4545 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4546 if (IS_ERR(full_path)) {
4547 rc = PTR_ERR(full_path);
4548 full_path = NULL;
4549 break;
4550 }
4551
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004552 old_mountdata = cifs_sb->mountdata;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004553 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004554 true);
4555 if (rc)
4556 break;
Jeff Layton7b91e262009-07-23 15:22:30 -04004557
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004558 if (cifs_sb->mountdata != old_mountdata) {
4559 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4560 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4561 &tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004562 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004563 if (rc) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004564 if (rc == -EACCES || rc == -EOPNOTSUPP)
4565 break;
4566 /* Perform DFS failover to any other DFS targets */
4567 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4568 root_tcon->ses, &xid,
4569 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004570 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4571 !ses)
4572 goto error;
4573 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004574 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004575 cifs_put_tcon(root_tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004576
Jeff Layton9d002df2010-10-06 19:51:11 -04004577 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004578 goto error;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004579
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004580 spin_lock(&cifs_tcp_ses_lock);
4581 if (!tcon->dfs_path) {
4582 /* Save full path in new tcon to do failover when reconnecting tcons */
4583 tcon->dfs_path = full_path;
4584 full_path = NULL;
4585 tcon->remap = cifs_remap(cifs_sb);
4586 }
4587 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
YueHaibing2f0a6172018-12-18 01:34:39 +00004588 strlen(tcon->dfs_path),
4589 GFP_ATOMIC);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004590 if (!cifs_sb->origin_fullpath) {
4591 spin_unlock(&cifs_tcp_ses_lock);
4592 rc = -ENOMEM;
4593 goto error;
4594 }
4595 spin_unlock(&cifs_tcp_ses_lock);
4596
Paulo Alcantarae511d312018-11-14 17:16:44 -02004597 rc = dfs_cache_add_vol(vol, cifs_sb->origin_fullpath);
4598 if (rc) {
4599 kfree(cifs_sb->origin_fullpath);
4600 goto error;
4601 }
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004602 /*
4603 * After reconnecting to a different server, unique ids won't
4604 * match anymore, so we disable serverino. This prevents
4605 * dentry revalidation to think the dentry are stale (ESTALE).
4606 */
4607 cifs_autodisable_serverino(cifs_sb);
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004608out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004609 free_xid(xid);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004610 return mount_setup_tlink(cifs_sb, ses, tcon);
4611
4612error:
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004613 kfree(full_path);
4614 kfree(root_path);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004615 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 return rc;
4617}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004618#else
4619int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4620{
4621 int rc = 0;
4622 unsigned int xid;
4623 struct cifs_ses *ses;
4624 struct cifs_tcon *tcon;
4625 struct TCP_Server_Info *server;
4626
4627 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4628 if (rc)
4629 goto error;
4630
4631 if (tcon) {
4632 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4633 if (rc == -EREMOTE)
4634 rc = -EOPNOTSUPP;
4635 if (rc)
4636 goto error;
4637 }
4638
4639 free_xid(xid);
4640
4641 return mount_setup_tlink(cifs_sb, ses, tcon);
4642
4643error:
4644 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4645 return rc;
4646}
4647#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648
Jeff Layton8d1bca32011-06-11 21:17:10 -04004649/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01004650 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04004651 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04004653CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00004654 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004655 const struct nls_table *nls_codepage)
4656{
4657 struct smb_hdr *smb_buffer;
4658 struct smb_hdr *smb_buffer_response;
4659 TCONX_REQ *pSMB;
4660 TCONX_RSP *pSMBr;
4661 unsigned char *bcc_ptr;
4662 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05004663 int length;
4664 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665
4666 if (ses == NULL)
4667 return -EIO;
4668
4669 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00004670 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004671 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00004672
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673 smb_buffer_response = smb_buffer;
4674
4675 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
4676 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07004677
Pavel Shilovsky88257362012-05-23 14:01:59 +04004678 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004679 smb_buffer->Uid = ses->Suid;
4680 pSMB = (TCONX_REQ *) smb_buffer;
4681 pSMBr = (TCONX_RSP *) smb_buffer_response;
4682
4683 pSMB->AndXCommand = 0xFF;
4684 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01004686 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08004687 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00004688 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08004689 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00004690 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08004691 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004692 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08004693 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
4694 specified as required (when that support is added to
4695 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00004696 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08004697 by Samba (not sure whether other servers allow
4698 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00004699#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04004700 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05004701 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05004702 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00004703 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05004704 SECMODE_PW_ENCRYPT ? true : false,
4705 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00004706 else
4707#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06004708 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05004709 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05004710 if (rc) {
4711 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
4712 __func__, rc);
4713 cifs_buf_release(smb_buffer);
4714 return rc;
4715 }
Steve Frencheeac8042006-01-13 21:34:58 -08004716
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004717 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004718 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00004719 /* must align unicode strings */
4720 *bcc_ptr = 0; /* null byte password */
4721 bcc_ptr++;
4722 }
Steve Frencheeac8042006-01-13 21:34:58 -08004723 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724
Jeff Layton38d77c52013-05-26 07:01:00 -04004725 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4727
4728 if (ses->capabilities & CAP_STATUS32) {
4729 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
4730 }
4731 if (ses->capabilities & CAP_DFS) {
4732 smb_buffer->Flags2 |= SMBFLG2_DFS;
4733 }
4734 if (ses->capabilities & CAP_UNICODE) {
4735 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
4736 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06004737 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004738 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004739 (/* server len*/ + 256 /* share len */), nls_codepage);
4740 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741 bcc_ptr += 2; /* skip trailing null */
4742 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743 strcpy(bcc_ptr, tree);
4744 bcc_ptr += strlen(tree) + 1;
4745 }
4746 strcpy(bcc_ptr, "?????");
4747 bcc_ptr += strlen("?????");
4748 bcc_ptr += 1;
4749 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004750 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4751 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752 pSMB->ByteCount = cpu_to_le16(count);
4753
Steve French133672e2007-11-13 22:41:37 +00004754 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004755 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01004758 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004759 bool is_unicode;
4760
Linus Torvalds1da177e2005-04-16 15:20:36 -07004761 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004762 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763 tcon->tid = smb_buffer_response->Tid;
4764 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004765 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004766 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004767 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4768 is_unicode = true;
4769 else
4770 is_unicode = false;
4771
Jeff Laytoncc20c032009-04-30 07:16:21 -04004772
Steve French50c2f752007-07-13 00:33:32 +00004773 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004774 if (length == 3) {
4775 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4776 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004777 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01004778 tcon->ipc = true;
4779 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00004780 }
4781 } else if (length == 2) {
4782 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4783 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05004784 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004785 }
4786 }
Steve French50c2f752007-07-13 00:33:32 +00004787 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004788 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05004789 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04004790
4791 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004792 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004793 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004794 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004795 nls_codepage);
4796
Joe Perchesf96637b2013-05-04 22:12:25 -05004797 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004798
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004799 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004800 (smb_buffer_response->WordCount == 7))
4801 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004802 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4803 else
4804 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05004805 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004806 }
4807
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004808 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809 return rc;
4810}
4811
Al Viro2e32cf52013-10-03 12:53:37 -04004812static void delayed_free(struct rcu_head *p)
4813{
4814 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
4815 unload_nls(sbi->local_nls);
4816 kfree(sbi);
4817}
4818
Al Viro2a9b9952011-06-17 09:27:16 -04004819void
4820cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004821{
Jeff Laytonb647c352010-10-28 11:16:44 -04004822 struct rb_root *root = &cifs_sb->tlink_tree;
4823 struct rb_node *node;
4824 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004825
Jeff Layton2de970f2010-10-06 19:51:12 -04004826 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4827
Jeff Laytonb647c352010-10-28 11:16:44 -04004828 spin_lock(&cifs_sb->tlink_tree_lock);
4829 while ((node = rb_first(root))) {
4830 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4831 cifs_get_tlink(tlink);
4832 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4833 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004834
Jeff Laytonb647c352010-10-28 11:16:44 -04004835 spin_unlock(&cifs_sb->tlink_tree_lock);
4836 cifs_put_tlink(tlink);
4837 spin_lock(&cifs_sb->tlink_tree_lock);
4838 }
4839 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004840
Al Virod757d712011-06-17 09:42:43 -04004841 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02004842 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004843#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02004844 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004845 kfree(cifs_sb->origin_fullpath);
4846#endif
Al Viro2e32cf52013-10-03 12:53:37 -04004847 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00004848}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004849
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004850int
4851cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004852{
4853 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004854 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004855
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004856 if (!server->ops->need_neg || !server->ops->negotiate)
4857 return -ENOSYS;
4858
Jeff Layton198b5682010-04-24 07:57:48 -04004859 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004860 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04004861 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004862
Pavel Shilovsky45275782012-05-17 17:53:29 +04004863 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004864
4865 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04004866 if (rc == 0) {
4867 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004868 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004869 server->tcpStatus = CifsGood;
4870 else
4871 rc = -EHOSTDOWN;
4872 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004873 }
Steve French26b994f2008-08-06 05:11:33 +00004874
Jeff Layton198b5682010-04-24 07:57:48 -04004875 return rc;
4876}
Steve French26b994f2008-08-06 05:11:33 +00004877
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004878int
4879cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
4880 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04004881{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004882 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04004883 struct TCP_Server_Info *server = ses->server;
4884
Jeff Layton198b5682010-04-24 07:57:48 -04004885 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004886 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004887 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00004888
Joe Perchesf96637b2013-05-04 22:12:25 -05004889 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00004890 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004891
Shu Wangf5c4ba82017-09-08 18:48:33 +08004892 if (ses->auth_key.response) {
Steve French2a182872018-03-29 12:16:34 -05004893 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
Shu Wangf5c4ba82017-09-08 18:48:33 +08004894 ses->auth_key.response);
4895 kfree(ses->auth_key.response);
4896 ses->auth_key.response = NULL;
4897 ses->auth_key.len = 0;
4898 }
4899
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004900 if (server->ops->sess_setup)
4901 rc = server->ops->sess_setup(xid, ses, nls_info);
4902
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05004903 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05004904 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004905
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906 return rc;
4907}
4908
Jeff Layton8a8798a2012-01-17 16:09:15 -05004909static int
4910cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4911{
Jeff Layton3f618222013-06-12 19:52:14 -05004912 vol->sectype = ses->sectype;
4913
4914 /* krb5 is special, since we don't need username or pw */
4915 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05004916 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05004917
4918 return cifs_set_cifscreds(vol, ses);
4919}
4920
Steve French96daf2b2011-05-27 04:34:02 +00004921static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004922cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04004923{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004924 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004925 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4926 struct cifs_ses *ses;
4927 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004928 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004929
4930 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004931 if (vol_info == NULL)
4932 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004933
Jeff Layton9d002df2010-10-06 19:51:11 -04004934 vol_info->local_nls = cifs_sb->local_nls;
4935 vol_info->linux_uid = fsuid;
4936 vol_info->cred_uid = fsuid;
4937 vol_info->UNC = master_tcon->treeName;
4938 vol_info->retry = master_tcon->retry;
4939 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05004940 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04004941 vol_info->local_lease = master_tcon->local_lease;
4942 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004943 vol_info->sectype = master_tcon->ses->sectype;
4944 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004945
Jeff Layton8a8798a2012-01-17 16:09:15 -05004946 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4947 if (rc) {
4948 tcon = ERR_PTR(rc);
4949 goto out;
4950 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004951
4952 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304953 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004954 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304955 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004956
4957 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4958 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004959 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004960 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04004961 goto out;
4962 }
4963
4964 tcon = cifs_get_tcon(ses, vol_info);
4965 if (IS_ERR(tcon)) {
4966 cifs_put_smb_ses(ses);
4967 goto out;
4968 }
4969
Steve Frenchce558b02018-05-31 19:16:54 -05004970 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4971 if (tcon->posix_extensions)
4972 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05004973
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004974 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004975 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05004976
Jeff Layton9d002df2010-10-06 19:51:11 -04004977out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004978 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01004979 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004980 kfree(vol_info);
4981
4982 return tcon;
4983}
4984
Steve French96daf2b2011-05-27 04:34:02 +00004985struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004986cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4987{
4988 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4989}
4990
Jeff Laytonb647c352010-10-28 11:16:44 -04004991/* find and return a tlink with given uid */
4992static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004993tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04004994{
4995 struct rb_node *node = root->rb_node;
4996 struct tcon_link *tlink;
4997
4998 while (node) {
4999 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5000
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005001 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005002 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005003 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005004 node = node->rb_right;
5005 else
5006 return tlink;
5007 }
5008 return NULL;
5009}
5010
5011/* insert a tcon_link into the tree */
5012static void
5013tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5014{
5015 struct rb_node **new = &(root->rb_node), *parent = NULL;
5016 struct tcon_link *tlink;
5017
5018 while (*new) {
5019 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5020 parent = *new;
5021
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005022 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005023 new = &((*new)->rb_left);
5024 else
5025 new = &((*new)->rb_right);
5026 }
5027
5028 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5029 rb_insert_color(&new_tlink->tl_rbnode, root);
5030}
5031
Jeff Layton9d002df2010-10-06 19:51:11 -04005032/*
5033 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5034 * current task.
5035 *
5036 * If the superblock doesn't refer to a multiuser mount, then just return
5037 * the master tcon for the mount.
5038 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305039 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005040 * exists, then check to see if it's pending construction. If it is then wait
5041 * for construction to complete. Once it's no longer pending, check to see if
5042 * it failed and either return an error or retry construction, depending on
5043 * the timeout.
5044 *
5045 * If one doesn't exist then insert a new tcon_link struct into the tree and
5046 * try to construct a new one.
5047 */
5048struct tcon_link *
5049cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5050{
5051 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005052 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005053 struct tcon_link *tlink, *newtlink;
5054
5055 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5056 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5057
5058 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005059 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005060 if (tlink)
5061 cifs_get_tlink(tlink);
5062 spin_unlock(&cifs_sb->tlink_tree_lock);
5063
5064 if (tlink == NULL) {
5065 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5066 if (newtlink == NULL)
5067 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005068 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005069 newtlink->tl_tcon = ERR_PTR(-EACCES);
5070 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5071 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5072 cifs_get_tlink(newtlink);
5073
Jeff Layton9d002df2010-10-06 19:51:11 -04005074 spin_lock(&cifs_sb->tlink_tree_lock);
5075 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005076 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005077 if (tlink) {
5078 cifs_get_tlink(tlink);
5079 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005080 kfree(newtlink);
5081 goto wait_for_construction;
5082 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005083 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005084 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5085 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005086 } else {
5087wait_for_construction:
5088 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005089 TASK_INTERRUPTIBLE);
5090 if (ret) {
5091 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005092 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005093 }
5094
5095 /* if it's good, return it */
5096 if (!IS_ERR(tlink->tl_tcon))
5097 return tlink;
5098
5099 /* return error if we tried this already recently */
5100 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5101 cifs_put_tlink(tlink);
5102 return ERR_PTR(-EACCES);
5103 }
5104
5105 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5106 goto wait_for_construction;
5107 }
5108
5109 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5110 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5111 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5112
5113 if (IS_ERR(tlink->tl_tcon)) {
5114 cifs_put_tlink(tlink);
5115 return ERR_PTR(-EACCES);
5116 }
5117
5118 return tlink;
5119}
Jeff Layton2de970f2010-10-06 19:51:12 -04005120
5121/*
5122 * periodic workqueue job that scans tcon_tree for a superblock and closes
5123 * out tcons.
5124 */
5125static void
5126cifs_prune_tlinks(struct work_struct *work)
5127{
5128 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5129 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005130 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005131 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005132 struct rb_node *tmp;
5133 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005134
Jeff Laytonb647c352010-10-28 11:16:44 -04005135 /*
5136 * Because we drop the spinlock in the loop in order to put the tlink
5137 * it's not guarded against removal of links from the tree. The only
5138 * places that remove entries from the tree are this function and
5139 * umounts. Because this function is non-reentrant and is canceled
5140 * before umount can proceed, this is safe.
5141 */
5142 spin_lock(&cifs_sb->tlink_tree_lock);
5143 node = rb_first(root);
5144 while (node != NULL) {
5145 tmp = node;
5146 node = rb_next(tmp);
5147 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5148
5149 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5150 atomic_read(&tlink->tl_count) != 0 ||
5151 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5152 continue;
5153
5154 cifs_get_tlink(tlink);
5155 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5156 rb_erase(tmp, root);
5157
Jeff Layton2de970f2010-10-06 19:51:12 -04005158 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005159 cifs_put_tlink(tlink);
5160 spin_lock(&cifs_sb->tlink_tree_lock);
5161 }
5162 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005163
Jeff Laytonda472fc2012-03-23 14:40:53 -04005164 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005165 TLINK_IDLE_EXPIRE);
5166}