blob: 683310f261718d3d07088342fde4b89a27bac4bc [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
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200328/*
329 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
330 * get their ip addresses changed at some point.
331 *
332 * This should be called with server->srv_mutex held.
333 */
334#ifdef CONFIG_CIFS_DFS_UPCALL
335static int reconn_set_ipaddr(struct TCP_Server_Info *server)
336{
337 int rc;
338 int len;
339 char *unc, *ipaddr = NULL;
340
341 if (!server->hostname)
342 return -EINVAL;
343
344 len = strlen(server->hostname) + 3;
345
346 unc = kmalloc(len, GFP_KERNEL);
347 if (!unc) {
348 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
349 return -ENOMEM;
350 }
351 snprintf(unc, len, "\\\\%s", server->hostname);
352
353 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
354 kfree(unc);
355
356 if (rc < 0) {
357 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
358 __func__, server->hostname, rc);
359 return rc;
360 }
361
362 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
363 strlen(ipaddr));
364 kfree(ipaddr);
365
366 return !rc ? -1 : 0;
367}
368#else
369static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
370{
371 return 0;
372}
373#endif
374
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200375#ifdef CONFIG_CIFS_DFS_UPCALL
376struct super_cb_data {
377 struct TCP_Server_Info *server;
378 struct cifs_sb_info *cifs_sb;
379};
380
381/* These functions must be called with server->srv_mutex held */
382
383static void super_cb(struct super_block *sb, void *arg)
384{
385 struct super_cb_data *d = arg;
386 struct cifs_sb_info *cifs_sb;
387 struct cifs_tcon *tcon;
388
389 if (d->cifs_sb)
390 return;
391
392 cifs_sb = CIFS_SB(sb);
393 tcon = cifs_sb_master_tcon(cifs_sb);
394 if (tcon->ses->server == d->server)
395 d->cifs_sb = cifs_sb;
396}
397
398static inline struct cifs_sb_info *
399find_super_by_tcp(struct TCP_Server_Info *server)
400{
401 struct super_cb_data d = {
402 .server = server,
403 .cifs_sb = NULL,
404 };
405
406 iterate_supers_type(&cifs_fs_type, super_cb, &d);
407 return d.cifs_sb ? d.cifs_sb : ERR_PTR(-ENOENT);
408}
409
410static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
411 struct cifs_sb_info *cifs_sb,
412 struct dfs_cache_tgt_list *tgt_list,
413 struct dfs_cache_tgt_iterator **tgt_it)
414{
415 const char *name;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200416
417 if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list ||
418 !server->nr_targets)
419 return;
420
421 if (!*tgt_it) {
422 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
423 } else {
424 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
425 if (!*tgt_it)
426 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
427 }
428
429 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
430
431 name = dfs_cache_get_tgt_name(*tgt_it);
432
433 kfree(server->hostname);
434
435 server->hostname = extract_hostname(name);
Dan Carpenter84288172019-01-05 15:25:29 +0300436 if (IS_ERR(server->hostname)) {
437 cifs_dbg(FYI,
438 "%s: failed to extract hostname from target: %ld\n",
439 __func__, PTR_ERR(server->hostname));
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200440 }
441}
442
443static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
444 struct dfs_cache_tgt_list *tl,
445 struct dfs_cache_tgt_iterator **it)
446{
447 if (!cifs_sb->origin_fullpath)
448 return -EOPNOTSUPP;
449 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
450}
451#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
Jeff Laytond5c56052008-12-01 18:42:33 -0500453/*
454 * cifs tcp session reconnection
455 *
456 * mark tcp session as reconnecting so temporarily locked
457 * mark all smb sessions as reconnecting for tcp session
458 * reconnect tcp session
459 * wake up waiters on reconnection? - (not needed currently)
460 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400461int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462cifs_reconnect(struct TCP_Server_Info *server)
463{
464 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500465 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000466 struct cifs_ses *ses;
467 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000468 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400469 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200470#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara23324402018-11-20 14:37:18 -0200471 struct cifs_sb_info *cifs_sb = NULL;
472 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200473 struct dfs_cache_tgt_iterator *tgt_it = NULL;
474#endif
Steve French50c2f752007-07-13 00:33:32 +0000475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200477 server->nr_targets = 1;
478#ifdef CONFIG_CIFS_DFS_UPCALL
479 cifs_sb = find_super_by_tcp(server);
480 if (IS_ERR(cifs_sb)) {
481 rc = PTR_ERR(cifs_sb);
482 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
483 __func__, rc);
484 cifs_sb = NULL;
485 } else {
486 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
Steve French55a7f002019-01-01 17:19:45 -0600487 if (rc && (rc != -EOPNOTSUPP)) {
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200488 cifs_dbg(VFS, "%s: no target servers for DFS failover\n",
489 __func__);
490 } else {
491 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
492 }
493 }
494 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
495 server->nr_targets);
496#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000497 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000498 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 next time through the loop */
500 spin_unlock(&GlobalMid_Lock);
501 return rc;
502 } else
503 server->tcpStatus = CifsNeedReconnect;
504 spin_unlock(&GlobalMid_Lock);
505 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400506 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Steve French6e4d3bb2018-09-22 11:25:04 -0500508 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500509 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
511 /* before reconnecting the tcp session, mark the smb session (uid)
512 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500513 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
514 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530515 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500516 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000517 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500518 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500519 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000520 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500521 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100523 if (ses->tcon_ipc)
524 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530526 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500527
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500529 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500530 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000531 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500532 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
533 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800534 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500535 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
536 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 sock_release(server->ssocket);
538 server->ssocket = NULL;
539 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500540 server->sequence_number = 0;
541 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500542 kfree(server->session_key.response);
543 server->session_key.response = NULL;
544 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000545 server->lstrp = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500547 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400548 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500549 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500551 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
552 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400553 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
554 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400555 list_move(&mid_entry->qhead, &retry_list);
556 }
557 spin_unlock(&GlobalMid_Lock);
Rabin Vincent820962d2015-12-23 07:32:41 +0100558 mutex_unlock(&server->srv_mutex);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400559
Joe Perchesf96637b2013-05-04 22:12:25 -0500560 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400561 list_for_each_safe(tmp, tmp2, &retry_list) {
562 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500563 list_del_init(&mid_entry->qhead);
564 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400567 do {
Steve French6c3d8902006-07-31 22:46:20 +0000568 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300569
Jeff Layton73e216a2013-09-05 08:38:10 -0400570 mutex_lock(&server->srv_mutex);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200571 /*
572 * Set up next DFS target server (if any) for reconnect. If DFS
573 * feature is disabled, then we will retry last server we
574 * connected to before.
575 */
Long Li781a8052017-11-22 17:38:36 -0700576 if (cifs_rdma_enabled(server))
577 rc = smbd_reconnect(server);
578 else
579 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000580 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500581 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200582#ifdef CONFIG_CIFS_DFS_UPCALL
583 reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
584 &tgt_it);
585#endif
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200586 rc = reconn_set_ipaddr(server);
587 if (rc) {
588 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
589 __func__, rc);
590 }
Federico Sauter4afe2602015-03-17 17:45:28 +0100591 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700592 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 } else {
594 atomic_inc(&tcpSesReconnectCount);
595 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000596 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000597 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000598 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100599 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400601 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500602
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200603#ifdef CONFIG_CIFS_DFS_UPCALL
604 if (tgt_it) {
605 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
606 tgt_it);
607 if (rc) {
608 cifs_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
609 __func__, rc);
610 }
611 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
612 if (rc) {
613 cifs_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
614 __func__, rc);
615 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200616 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200617 }
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200618#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400619 if (server->tcpStatus == CifsNeedNegotiate)
620 mod_delayed_work(cifsiod_wq, &server->echo, 0);
621
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 return rc;
623}
624
Jeff Laytonc74093b2011-01-11 07:24:23 -0500625static void
626cifs_echo_request(struct work_struct *work)
627{
628 int rc;
629 struct TCP_Server_Info *server = container_of(work,
630 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400631 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500632
Jeff Layton247ec9b2011-02-04 17:09:50 -0500633 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400634 * If we need to renegotiate, set echo interval to zero to
635 * immediately call echo service where we can renegotiate.
636 */
637 if (server->tcpStatus == CifsNeedNegotiate)
638 echo_interval = 0;
639 else
640 echo_interval = server->echo_interval;
641
642 /*
643 * We cannot send an echo if it is disabled.
644 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500645 */
Steve French4fcd1812016-06-22 20:12:05 -0500646
647 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400648 server->tcpStatus == CifsExiting ||
649 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400650 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600651 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500652 goto requeue_echo;
653
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400654 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500655 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500656 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
657 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500658
659requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400660 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500661}
662
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400663static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400664allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400665{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400666 if (!server->bigbuf) {
667 server->bigbuf = (char *)cifs_buf_get();
668 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500669 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400670 msleep(3000);
671 /* retry will check if exiting */
672 return false;
673 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400674 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400675 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400676 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400677 }
678
Jeff Layton2a37ef92011-10-19 15:29:23 -0400679 if (!server->smallbuf) {
680 server->smallbuf = (char *)cifs_small_buf_get();
681 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500682 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400683 msleep(1000);
684 /* retry will check if exiting */
685 return false;
686 }
687 /* beginning of smb buffer is cleared in our buf_get */
688 } else {
689 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400690 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400691 }
692
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400693 return true;
694}
695
Jeff Laytonba749e62011-10-11 06:41:32 -0400696static bool
697server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400698{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300699 /*
700 * We need to wait 2 echo intervals to make sure we handle such
701 * situations right:
702 * 1s client sends a normal SMB request
703 * 2s client gets a response
704 * 30s echo workqueue job pops, and decides we got a response recently
705 * and don't need to send another
706 * ...
707 * 65s kernel_recvmsg times out, and we see that we haven't gotten
708 * a response in >60s.
709 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200710 if ((server->tcpStatus == CifsGood ||
711 server->tcpStatus == CifsNeedNegotiate) &&
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600712 time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
713 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
714 server->hostname, (2 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400715 cifs_reconnect(server);
716 wake_up(&server->response_q);
717 return true;
718 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400719
Jeff Laytonba749e62011-10-11 06:41:32 -0400720 return false;
721}
722
Al Viro71335662016-01-09 19:54:50 -0500723static int
724cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400725{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400726 int length = 0;
727 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400728
Al Viro71335662016-01-09 19:54:50 -0500729 smb_msg->msg_control = NULL;
730 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400731
Al Viro71335662016-01-09 19:54:50 -0500732 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500733 try_to_freeze();
734
Al Viro71335662016-01-09 19:54:50 -0500735 if (server_unresponsive(server))
736 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700737 if (cifs_rdma_enabled(server) && server->smbd_conn)
738 length = smbd_recv(server->smbd_conn, smb_msg);
739 else
740 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500741
742 if (server->tcpStatus == CifsExiting)
743 return -ESHUTDOWN;
744
745 if (server->tcpStatus == CifsNeedReconnect) {
746 cifs_reconnect(server);
747 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400748 }
749
Al Viro71335662016-01-09 19:54:50 -0500750 if (length == -ERESTARTSYS ||
751 length == -EAGAIN ||
752 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400753 /*
754 * Minimum sleep to prevent looping, allowing socket
755 * to clear and app threads to set tcpStatus
756 * CifsNeedReconnect if server hung.
757 */
758 usleep_range(1000, 2000);
759 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400760 continue;
Al Viro71335662016-01-09 19:54:50 -0500761 }
762
763 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500764 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400765 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500766 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400767 }
768 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400769 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400770}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400771
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400772int
773cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
774 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400775{
Al Viro71335662016-01-09 19:54:50 -0500776 struct msghdr smb_msg;
777 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100778 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400779
Al Viro71335662016-01-09 19:54:50 -0500780 return cifs_readv_from_socket(server, &smb_msg);
781}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400782
Al Viro71335662016-01-09 19:54:50 -0500783int
784cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700785 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500786{
787 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700788 struct bio_vec bv = {
789 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100790 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500791 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400792}
793
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400794static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400795is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400796{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400797 /*
798 * The first byte big endian of the length field,
799 * is actually not part of the length but the type
800 * with the most common, zero, as regular data.
801 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400802 switch (type) {
803 case RFC1002_SESSION_MESSAGE:
804 /* Regular SMB response */
805 return true;
806 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500807 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400808 break;
809 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500810 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400811 break;
812 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400813 /*
814 * We get this from Windows 98 instead of an error on
815 * SMB negprot response.
816 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500817 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400818 /* give server a second to clean up */
819 msleep(1000);
820 /*
821 * Always try 445 first on reconnect since we get NACK
822 * on some if we ever connected to port 139 (the NACK
823 * is since we do not begin with RFC1001 session
824 * initialize frame).
825 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400826 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400827 cifs_reconnect(server);
828 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400829 break;
830 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500831 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400832 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400833 }
834
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400835 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400836}
837
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400838void
839dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400840{
841#ifdef CONFIG_CIFS_STATS2
842 mid->when_received = jiffies;
843#endif
844 spin_lock(&GlobalMid_Lock);
845 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400846 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400847 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400848 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000849 /*
850 * Trying to handle/dequeue a mid after the send_recv()
851 * function has finished processing it is a bug.
852 */
853 if (mid->mid_flags & MID_DELETED)
854 printk_once(KERN_WARNING
855 "trying to dequeue a deleted mid\n");
856 else
857 list_del_init(&mid->qhead);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400858 spin_unlock(&GlobalMid_Lock);
859}
860
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400861static void
862handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400863 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400864{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400865 if (server->ops->check_trans2 &&
866 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400867 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400868 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400869 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400870 /* Was previous buf put in mpx struct for multi-rsp? */
871 if (!mid->multiRsp) {
872 /* smb buffer will be freed by user thread */
873 if (server->large_buf)
874 server->bigbuf = NULL;
875 else
876 server->smallbuf = NULL;
877 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400878 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400879}
880
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400881static void clean_demultiplex_info(struct TCP_Server_Info *server)
882{
883 int length;
884
885 /* take it off the list, if it's not already */
886 spin_lock(&cifs_tcp_ses_lock);
887 list_del_init(&server->tcp_ses_list);
888 spin_unlock(&cifs_tcp_ses_lock);
889
890 spin_lock(&GlobalMid_Lock);
891 server->tcpStatus = CifsExiting;
892 spin_unlock(&GlobalMid_Lock);
893 wake_up_all(&server->response_q);
894
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400895 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300896 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400897 if (server->credits <= 0)
898 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300899 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400900 /*
901 * Although there should not be any requests blocked on this queue it
902 * can not hurt to be paranoid and try to wake up requests that may
903 * haven been blocked when more than 50 at time were on the wire to the
904 * same server - they now will see the session is in exit state and get
905 * out of SendReceive.
906 */
907 wake_up_all(&server->request_q);
908 /* give those requests time to exit */
909 msleep(125);
Long Libce9ce72017-11-22 17:38:38 -0700910 if (cifs_rdma_enabled(server) && server->smbd_conn) {
911 smbd_destroy(server->smbd_conn);
912 server->smbd_conn = NULL;
913 }
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400914 if (server->ssocket) {
915 sock_release(server->ssocket);
916 server->ssocket = NULL;
917 }
918
919 if (!list_empty(&server->pending_mid_q)) {
920 struct list_head dispose_list;
921 struct mid_q_entry *mid_entry;
922 struct list_head *tmp, *tmp2;
923
924 INIT_LIST_HEAD(&dispose_list);
925 spin_lock(&GlobalMid_Lock);
926 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
927 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500928 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400929 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400930 list_move(&mid_entry->qhead, &dispose_list);
931 }
932 spin_unlock(&GlobalMid_Lock);
933
934 /* now walk dispose list and issue callbacks */
935 list_for_each_safe(tmp, tmp2, &dispose_list) {
936 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500937 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400938 list_del_init(&mid_entry->qhead);
939 mid_entry->callback(mid_entry);
940 }
941 /* 1/8th of sec is more than enough time for them to exit */
942 msleep(125);
943 }
944
945 if (!list_empty(&server->pending_mid_q)) {
946 /*
947 * mpx threads have not exited yet give them at least the smb
948 * send timeout time for long ops.
949 *
950 * Due to delays on oplock break requests, we need to wait at
951 * least 45 seconds before giving up on a request getting a
952 * response and going ahead and killing cifsd.
953 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500954 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400955 msleep(46000);
956 /*
957 * If threads still have not exited they are probably never
958 * coming home not much else we can do but free the memory.
959 */
960 }
961
962 kfree(server->hostname);
963 kfree(server);
964
965 length = atomic_dec_return(&tcpSesAllocCount);
966 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700967 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400968}
969
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400970static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400971standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
972{
973 int length;
974 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +1000975 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400976
977 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100978 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
979 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500980 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400981 cifs_reconnect(server);
982 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400983 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400984 }
985
986 /* switch to large buffer if too big for a small one */
987 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
988 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400989 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400990 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400991 }
992
993 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400994 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100995 pdu_length - HEADER_SIZE(server) + 1
996 + server->vals->header_preamble_size);
997
Jeff Laytone9097ab2011-10-19 15:29:40 -0400998 if (length < 0)
999 return length;
1000 server->total_read += length;
1001
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001002 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001003
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08001004 return cifs_handle_standard(server, mid);
1005}
1006
1007int
1008cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1009{
1010 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1011 int length;
1012
Jeff Laytone9097ab2011-10-19 15:29:40 -04001013 /*
1014 * We know that we received enough to get to the MID as we
1015 * checked the pdu_length earlier. Now check to see
1016 * if the rest of the header is OK. We borrow the length
1017 * var for the rest of the loop to avoid a new stack var.
1018 *
1019 * 48 bytes is enough to display the header and a little bit
1020 * into the payload for debugging purposes.
1021 */
Steve French373512e2015-12-18 13:05:30 -06001022 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001023 if (length != 0)
1024 cifs_dump_mem("Bad SMB: ", buf,
1025 min_t(unsigned int, server->total_read, 48));
1026
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001027 if (server->ops->is_session_expired &&
1028 server->ops->is_session_expired(buf)) {
1029 cifs_reconnect(server);
1030 wake_up(&server->response_q);
1031 return -1;
1032 }
1033
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001034 if (server->ops->is_status_pending &&
1035 server->ops->is_status_pending(buf, server, length))
1036 return -1;
1037
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001038 if (!mid)
1039 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001040
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001041 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001042 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001043}
1044
1045static int
Al Viro7c97c202011-06-21 08:51:28 -04001046cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001048 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001049 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001050 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001051 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001052 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001053 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001054 struct mid_q_entry *mids[MAX_COMPOUND];
1055 char *bufs[MAX_COMPOUND];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -05001058 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001059
1060 length = atomic_inc_return(&tcpSesAllocCount);
1061 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001062 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001064 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +00001065 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001066 if (try_to_freeze())
1067 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001068
Jeff Layton2a37ef92011-10-19 15:29:23 -04001069 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001070 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001071
Jeff Layton2a37ef92011-10-19 15:29:23 -04001072 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001073 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001074 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001075
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001076 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001077 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001078 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001079
1080 if (server->vals->header_preamble_size == 0)
1081 server->total_read = 0;
1082 else
1083 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001084
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001085 /*
1086 * The right amount was read from socket - 4 bytes,
1087 * so we can now interpret the length field.
1088 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001089 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001090
Joe Perchesf96637b2013-05-04 22:12:25 -05001091 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001092 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001093 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001094next_pdu:
1095 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001096
Jeff Layton89482a52011-10-19 15:28:57 -04001097 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001098 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001099 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001100 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001101 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001102 cifs_reconnect(server);
1103 wake_up(&server->response_q);
1104 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001105 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001106
Jeff Layton89482a52011-10-19 15:28:57 -04001107 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001108 length = cifs_read_from_socket(server,
1109 buf + server->vals->header_preamble_size,
1110 HEADER_SIZE(server) - 1
1111 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001112 if (length < 0)
1113 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001114 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001115
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001116 if (server->ops->next_header) {
1117 next_offset = server->ops->next_header(buf);
1118 if (next_offset)
1119 server->pdu_size = next_offset;
1120 }
1121
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001122 memset(mids, 0, sizeof(mids));
1123 memset(bufs, 0, sizeof(bufs));
1124 num_mids = 0;
1125
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001126 if (server->ops->is_transform_hdr &&
1127 server->ops->receive_transform &&
1128 server->ops->is_transform_hdr(buf)) {
1129 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001130 mids,
1131 bufs,
1132 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001133 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001134 mids[0] = server->ops->find_mid(server, buf);
1135 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001136 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001137
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001138 if (!mids[0] || !mids[0]->receive)
1139 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001140 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001141 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001142 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001143
Lars Persson696e4202018-06-25 14:05:25 +02001144 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001145 for (i = 0; i < num_mids; i++)
1146 if (mids[i])
1147 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001148 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001149 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001150
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001151 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -04001152 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -07001153
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001154
Steve Frenchfda35942011-01-20 18:06:34 +00001155 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001156
1157 for (i = 0; i < num_mids; i++) {
1158 if (mids[i] != NULL) {
1159 mids[i]->resp_buf_size = server->pdu_size;
1160 if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
1161 mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
1162 server->ops->handle_cancelled_mid)
1163 server->ops->handle_cancelled_mid(
1164 mids[i]->resp_buf,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001165 server);
1166
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001167 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1168 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001169
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001170 cifs_mid_q_entry_release(mids[i]);
1171 } else if (server->ops->is_oplock_break &&
1172 server->ops->is_oplock_break(bufs[i],
1173 server)) {
1174 cifs_dbg(FYI, "Received oplock break\n");
1175 } else {
1176 cifs_dbg(VFS, "No task to wake, unknown frame "
1177 "received! NumMids %d\n",
1178 atomic_read(&midCount));
1179 cifs_dump_mem("Received Data is: ", bufs[i],
1180 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +00001181#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001182 if (server->ops->dump_detail)
1183 server->ops->dump_detail(bufs[i],
1184 server);
1185 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001186#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001187 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001188 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001189
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001190 if (pdu_length > server->pdu_size) {
1191 if (!allocate_buffers(server))
1192 continue;
1193 pdu_length -= server->pdu_size;
1194 server->total_read = 0;
1195 server->large_buf = false;
1196 buf = server->smallbuf;
1197 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001198 }
1199 } /* end while !EXITING */
1200
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001201 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001202 cifs_buf_release(server->bigbuf);
1203 if (server->smallbuf) /* no sense logging a debug message if NULL */
1204 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001206 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001207 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001208
1209 /* if server->tsk was NULL then wait for a signal before exiting */
1210 if (!task_to_wake) {
1211 set_current_state(TASK_INTERRUPTIBLE);
1212 while (!signal_pending(current)) {
1213 schedule();
1214 set_current_state(TASK_INTERRUPTIBLE);
1215 }
1216 set_current_state(TASK_RUNNING);
1217 }
1218
Jeff Layton0468a2c2008-12-01 07:09:35 -05001219 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220}
1221
Jeff Laytonc359cf32007-11-16 22:22:06 +00001222/* extract the host portion of the UNC string */
1223static char *
1224extract_hostname(const char *unc)
1225{
1226 const char *src;
1227 char *dst, *delim;
1228 unsigned int len;
1229
1230 /* skip double chars at beginning of string */
1231 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001232 if (strlen(unc) < 3)
1233 return ERR_PTR(-EINVAL);
1234 for (src = unc; *src && *src == '\\'; src++)
1235 ;
1236 if (!*src)
1237 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001238
1239 /* delimiter between hostname and sharename is always '\\' now */
1240 delim = strchr(src, '\\');
1241 if (!delim)
1242 return ERR_PTR(-EINVAL);
1243
1244 len = delim - src;
1245 dst = kmalloc((len + 1), GFP_KERNEL);
1246 if (dst == NULL)
1247 return ERR_PTR(-ENOMEM);
1248
1249 memcpy(dst, src, len);
1250 dst[len] = '\0';
1251
1252 return dst;
1253}
1254
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001255static int get_option_ul(substring_t args[], unsigned long *option)
1256{
1257 int rc;
1258 char *string;
1259
1260 string = match_strdup(args);
1261 if (string == NULL)
1262 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001263 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001264 kfree(string);
1265
1266 return rc;
1267}
1268
Eric W. Biederman3da46562013-02-06 01:37:39 -08001269static int get_option_uid(substring_t args[], kuid_t *result)
1270{
1271 unsigned long value;
1272 kuid_t uid;
1273 int rc;
1274
1275 rc = get_option_ul(args, &value);
1276 if (rc)
1277 return rc;
1278
1279 uid = make_kuid(current_user_ns(), value);
1280 if (!uid_valid(uid))
1281 return -EINVAL;
1282
1283 *result = uid;
1284 return 0;
1285}
1286
1287static int get_option_gid(substring_t args[], kgid_t *result)
1288{
1289 unsigned long value;
1290 kgid_t gid;
1291 int rc;
1292
1293 rc = get_option_ul(args, &value);
1294 if (rc)
1295 return rc;
1296
1297 gid = make_kgid(current_user_ns(), value);
1298 if (!gid_valid(gid))
1299 return -EINVAL;
1300
1301 *result = gid;
1302 return 0;
1303}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001304
1305static int cifs_parse_security_flavors(char *value,
1306 struct smb_vol *vol)
1307{
1308
1309 substring_t args[MAX_OPT_ARGS];
1310
Jeff Layton1e3cc572013-06-10 17:12:23 -05001311 /*
1312 * With mount options, the last one should win. Reset any existing
1313 * settings back to default.
1314 */
1315 vol->sectype = Unspecified;
1316 vol->sign = false;
1317
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001318 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001319 case Opt_sec_krb5p:
1320 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1321 return 1;
1322 case Opt_sec_krb5i:
1323 vol->sign = true;
1324 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001325 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001326 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001327 break;
1328 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001329 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001330 /* Fallthrough */
1331 case Opt_sec_ntlmssp:
1332 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001333 break;
1334 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001335 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001336 /* Fallthrough */
1337 case Opt_ntlm:
1338 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001339 break;
1340 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001341 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001342 /* Fallthrough */
1343 case Opt_sec_ntlmv2:
1344 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001345 break;
1346#ifdef CONFIG_CIFS_WEAK_PW_HASH
1347 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001348 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001349 break;
1350#endif
1351 case Opt_sec_none:
1352 vol->nullauth = 1;
1353 break;
1354 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001355 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001356 return 1;
1357 }
1358
1359 return 0;
1360}
1361
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001363cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1364{
1365 substring_t args[MAX_OPT_ARGS];
1366
1367 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1368 case Opt_cache_loose:
1369 vol->direct_io = false;
1370 vol->strict_io = false;
1371 break;
1372 case Opt_cache_strict:
1373 vol->direct_io = false;
1374 vol->strict_io = true;
1375 break;
1376 case Opt_cache_none:
1377 vol->direct_io = true;
1378 vol->strict_io = false;
1379 break;
1380 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001381 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001382 return 1;
1383 }
1384 return 0;
1385}
1386
1387static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001388cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001389{
1390 substring_t args[MAX_OPT_ARGS];
1391
1392 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001393#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001394 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001395 if (disable_legacy_dialects) {
1396 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1397 return 1;
1398 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001399 if (is_smb3) {
1400 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1401 return 1;
1402 }
Jeff Layton23db65f2012-05-15 12:20:51 -04001403 vol->ops = &smb1_operations;
1404 vol->vals = &smb1_values;
1405 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001406 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001407 if (disable_legacy_dialects) {
1408 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1409 return 1;
1410 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001411 if (is_smb3) {
1412 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1413 return 1;
1414 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001415 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001416 vol->vals = &smb20_values;
1417 break;
Steve French74204512018-06-19 14:34:08 -05001418#else
1419 case Smb_1:
1420 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1421 return 1;
1422 case Smb_20:
1423 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1424 return 1;
1425#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001426 case Smb_21:
1427 vol->ops = &smb21_operations;
1428 vol->vals = &smb21_values;
1429 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001430 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001431 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001432 vol->vals = &smb30_values;
1433 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001434 case Smb_302:
1435 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1436 vol->vals = &smb302_values;
1437 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001438 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001439 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001440 vol->vals = &smb311_values;
1441 break;
Steve French9764c022017-09-17 10:41:35 -05001442 case Smb_3any:
1443 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1444 vol->vals = &smb3any_values;
1445 break;
1446 case Smb_default:
1447 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1448 vol->vals = &smbdefault_values;
1449 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001450 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001451 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001452 return 1;
1453 }
1454 return 0;
1455}
1456
Jeff Laytond387a5c2012-12-10 06:10:46 -05001457/*
1458 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1459 * fields with the result. Returns 0 on success and an error otherwise.
1460 */
1461static int
1462cifs_parse_devname(const char *devname, struct smb_vol *vol)
1463{
1464 char *pos;
1465 const char *delims = "/\\";
1466 size_t len;
1467
1468 /* make sure we have a valid UNC double delimiter prefix */
1469 len = strspn(devname, delims);
1470 if (len != 2)
1471 return -EINVAL;
1472
1473 /* find delimiter between host and sharename */
1474 pos = strpbrk(devname + 2, delims);
1475 if (!pos)
1476 return -EINVAL;
1477
1478 /* skip past delimiter */
1479 ++pos;
1480
1481 /* now go until next delimiter or end of string */
1482 len = strcspn(pos, delims);
1483
1484 /* move "pos" up to delimiter or NULL */
1485 pos += len;
1486 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1487 if (!vol->UNC)
1488 return -ENOMEM;
1489
1490 convert_delimiter(vol->UNC, '\\');
1491
Sachin Prabhu11e31642016-02-08 13:44:01 +05301492 /* skip any delimiter */
1493 if (*pos == '/' || *pos == '\\')
1494 pos++;
1495
1496 /* If pos is NULL then no prepath */
1497 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001498 return 0;
1499
1500 vol->prepath = kstrdup(pos, GFP_KERNEL);
1501 if (!vol->prepath)
1502 return -ENOMEM;
1503
1504 return 0;
1505}
1506
Jeff Layton23db65f2012-05-15 12:20:51 -04001507static int
Sean Finneyb9468452011-04-11 13:19:32 +00001508cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001509 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001511 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001512 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 unsigned int temp_len, i, j;
1514 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001515 short int override_uid = -1;
1516 short int override_gid = -1;
1517 bool uid_specified = false;
1518 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001519 bool sloppy = false;
1520 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001521 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001522 char *string = NULL;
1523 char *tmp_end, *value;
1524 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001525 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001526 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001527 unsigned short port = 0;
1528 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
1530 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001531 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001532 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
Jeff Layton6ee95422012-11-26 11:09:57 -05001534 /* ensure we always start with zeroed-out smb_vol */
1535 memset(vol, 0, sizeof(*vol));
1536
Jeff Layton88463992010-11-22 15:31:03 -05001537 /*
1538 * does not have to be perfect mapping since field is
1539 * informational, only used for servers that do not support
1540 * port 445 and it can be overridden at mount time
1541 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001542 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1543 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001544 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1545
Jeff Layton1397f2e2011-01-07 11:30:28 -05001546 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001547 /* null target name indicates to use *SMBSERVR default called name
1548 if we end up sending RFC1001 session initialize */
1549 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001550 vol->cred_uid = current_uid();
1551 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001552 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001553
Steve French2baa2682014-09-27 02:19:01 -05001554 /*
1555 * default to SFM style remapping of seven reserved characters
1556 * unless user overrides it or we negotiate CIFS POSIX where
1557 * it is unnecessary. Can not simultaneously use more than one mapping
1558 * since then readdir could list files that open could not open
1559 */
1560 vol->remap = true;
1561
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001562 /* default to only allowing write access to owner of the mount */
1563 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
1565 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001566 /* default is always to request posix paths. */
1567 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001568 /* default to using server inode numbers where available */
1569 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001570
Jeff Layton1b359202012-09-19 15:20:27 -07001571 /* default is to use strict cifs caching semantics */
1572 vol->strict_io = true;
1573
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301574 vol->actimeo = CIFS_DEF_ACTIMEO;
1575
Steve French9764c022017-09-17 10:41:35 -05001576 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1577 vol->ops = &smb30_operations;
1578 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001579
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001580 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1581
Sean Finneyb9468452011-04-11 13:19:32 +00001582 if (!mountdata)
1583 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
Sean Finneyb9468452011-04-11 13:19:32 +00001585 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1586 if (!mountdata_copy)
1587 goto cifs_parse_mount_err;
1588
1589 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001590 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001591
Steve French50c2f752007-07-13 00:33:32 +00001592 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001593 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 separator[0] = options[4];
1595 options += 5;
1596 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001597 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 }
1599 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001600 vol->backupuid_specified = false; /* no backup intent for a user */
1601 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001602
Jeff Layton37d4f992013-05-24 07:40:05 -04001603 switch (cifs_parse_devname(devname, vol)) {
1604 case 0:
1605 break;
1606 case -ENOMEM:
1607 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1608 goto cifs_parse_mount_err;
1609 case -EINVAL:
1610 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1611 goto cifs_parse_mount_err;
1612 default:
1613 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1614 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001615 }
1616
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001618 substring_t args[MAX_OPT_ARGS];
1619 unsigned long option;
1620 int token;
1621
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 if (!*data)
1623 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001625 token = match_token(data, cifs_mount_option_tokens, args);
1626
1627 switch (token) {
1628
1629 /* Ingnore the following */
1630 case Opt_ignore:
1631 break;
1632
1633 /* Boolean values */
1634 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001636 break;
1637 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001639 break;
1640 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001641 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001642 break;
1643 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001644 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001645 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001646 case Opt_forcegid:
1647 override_gid = 1;
1648 break;
1649 case Opt_noforcegid:
1650 override_gid = 0;
1651 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001652 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001653 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001654 break;
1655 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001656 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001657 break;
1658 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001660 break;
1661 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001663 break;
1664 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001666 break;
1667 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001669 break;
1670 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001671 vol->sfu_remap = true;
1672 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001673 break;
1674 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001675 vol->sfu_remap = false;
1676 break;
1677 case Opt_mapposix:
1678 vol->remap = true;
1679 vol->sfu_remap = false; /* disable SFU mapping */
1680 break;
1681 case Opt_nomapposix:
1682 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001683 break;
1684 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001685 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001686 break;
1687 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001688 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001689 break;
1690 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001691 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001692 break;
1693 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001694 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001695 break;
1696 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001697 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001698 break;
1699 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001700 if (vol->linux_ext)
1701 cifs_dbg(VFS,
1702 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001703 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001704 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001705 case Opt_unix:
1706 if (vol->no_linux_ext)
1707 cifs_dbg(VFS,
1708 "conflicting unix mount options\n");
1709 vol->linux_ext = 1;
1710 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001711 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001712 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001713 break;
1714 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001715 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001716 break;
1717 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001718 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001719 /*
1720 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001721 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001722 * local vfs will do advisory
1723 */
Steve French50c2f752007-07-13 00:33:32 +00001724 if (vol->file_mode ==
1725 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001726 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001727 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001728 case Opt_nohandlecache:
1729 vol->nohandlecache = 1;
1730 break;
1731 case Opt_handlecache:
1732 vol->nohandlecache = 0;
1733 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001734 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001735 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001736 break;
1737 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001739 break;
1740 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001742 break;
Steve French95932652016-09-23 01:36:34 -05001743 case Opt_setuidfromacl:
1744 vol->setuidfromacl = 1;
1745 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001746 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001747 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001748 break;
1749 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001750 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001751 break;
1752 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001754 break;
1755 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001757 break;
1758 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001760 break;
1761 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001763 break;
1764 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001765 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001766 break;
1767 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001768 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001769 break;
1770 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001772 break;
1773 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001775 break;
1776 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001777 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001778 break;
1779 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001780 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001781 break;
1782 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001783 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001784 break;
1785 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001787 break;
1788 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001790 break;
1791 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001792 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001793 break;
1794 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001795 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001796 break;
1797 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001798 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001799 * is a per tree connection (mount) not a per socket
1800 * or per-smb connection option in the protocol
1801 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1802 */
Steve French95b1cb92008-05-15 16:44:38 +00001803 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001804 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001805 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001806 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001807 break;
1808 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301809#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001810 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001811 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301812#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301813 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001814 break;
1815 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001816 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001817 break;
1818 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001819 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001820 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001821 case Opt_sloppy:
1822 sloppy = true;
1823 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001824 case Opt_nosharesock:
1825 vol->nosharesock = true;
1826 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001827 case Opt_nopersistent:
1828 vol->nopersistent = true;
1829 if (vol->persistent) {
1830 cifs_dbg(VFS,
1831 "persistenthandles mount options conflict\n");
1832 goto cifs_parse_mount_err;
1833 }
1834 break;
1835 case Opt_persistent:
1836 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001837 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001838 cifs_dbg(VFS,
1839 "persistenthandles mount options conflict\n");
1840 goto cifs_parse_mount_err;
1841 }
1842 break;
Steve French592fafe2015-11-03 10:08:53 -06001843 case Opt_resilient:
1844 vol->resilient = true;
1845 if (vol->persistent) {
1846 cifs_dbg(VFS,
1847 "persistenthandles mount options conflict\n");
1848 goto cifs_parse_mount_err;
1849 }
1850 break;
1851 case Opt_noresilient:
1852 vol->resilient = false; /* already the default */
1853 break;
Germano Percossi39566442016-12-15 12:31:18 +05301854 case Opt_domainauto:
1855 vol->domainauto = true;
1856 break;
Long Li8339dd32017-11-07 01:54:55 -07001857 case Opt_rdma:
1858 vol->rdma = true;
1859 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001860
1861 /* Numeric Values */
1862 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001863 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001864 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1865 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001866 goto cifs_parse_mount_err;
1867 }
1868 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001869 break;
1870 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001871 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001872 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1873 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001874 goto cifs_parse_mount_err;
1875 }
1876 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001877 break;
1878 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001879 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001880 cifs_dbg(VFS, "%s: Invalid uid value\n",
1881 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001882 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001884 uid_specified = true;
1885 break;
1886 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001887 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001888 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1889 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001890 goto cifs_parse_mount_err;
1891 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001892 break;
1893 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001894 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001895 cifs_dbg(VFS, "%s: Invalid gid value\n",
1896 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001897 goto cifs_parse_mount_err;
1898 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001899 gid_specified = true;
1900 break;
1901 case Opt_file_mode:
1902 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001903 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1904 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001905 goto cifs_parse_mount_err;
1906 }
1907 vol->file_mode = option;
1908 break;
1909 case Opt_dirmode:
1910 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001911 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1912 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001913 goto cifs_parse_mount_err;
1914 }
1915 vol->dir_mode = option;
1916 break;
1917 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001918 if (get_option_ul(args, &option) ||
1919 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001920 cifs_dbg(VFS, "%s: Invalid port value\n",
1921 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001922 goto cifs_parse_mount_err;
1923 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001924 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001925 break;
1926 case Opt_rsize:
1927 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001928 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1929 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001930 goto cifs_parse_mount_err;
1931 }
1932 vol->rsize = option;
1933 break;
1934 case Opt_wsize:
1935 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001936 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1937 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001938 goto cifs_parse_mount_err;
1939 }
1940 vol->wsize = option;
1941 break;
1942 case Opt_actimeo:
1943 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001944 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1945 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001946 goto cifs_parse_mount_err;
1947 }
1948 vol->actimeo = HZ * option;
1949 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001950 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001951 goto cifs_parse_mount_err;
1952 }
1953 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06001954 case Opt_echo_interval:
1955 if (get_option_ul(args, &option)) {
1956 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
1957 __func__);
1958 goto cifs_parse_mount_err;
1959 }
1960 vol->echo_interval = option;
1961 break;
Steve French8b217fe2016-11-11 22:36:20 -06001962 case Opt_snapshot:
1963 if (get_option_ul(args, &option)) {
1964 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
1965 __func__);
1966 goto cifs_parse_mount_err;
1967 }
1968 vol->snapshot_time = option;
1969 break;
Steve French141891f2016-09-23 00:44:16 -05001970 case Opt_max_credits:
1971 if (get_option_ul(args, &option) || (option < 20) ||
1972 (option > 60000)) {
1973 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1974 __func__);
1975 goto cifs_parse_mount_err;
1976 }
1977 vol->max_credits = option;
1978 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001979
1980 /* String Arguments */
1981
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001982 case Opt_blank_user:
1983 /* null user, ie. anonymous authentication */
1984 vol->nullauth = 1;
1985 vol->username = NULL;
1986 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001987 case Opt_user:
1988 string = match_strdup(args);
1989 if (string == NULL)
1990 goto out_nomem;
1991
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001992 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1993 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001994 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001995 goto cifs_parse_mount_err;
1996 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001997
1998 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001999 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05002000 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002001 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002002 break;
2003 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002004 /* passwords have to be handled differently
2005 * to allow the character used for deliminator
2006 * to be passed within them
2007 */
2008
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002009 /*
2010 * Check if this is a case where the password
2011 * starts with a delimiter
2012 */
2013 tmp_end = strchr(data, '=');
2014 tmp_end++;
2015 if (!(tmp_end < end && tmp_end[1] == delim)) {
2016 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002017 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002018 vol->password = NULL;
2019 break;
2020 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +11002021 /* Fallthrough - to Opt_pass below.*/
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002022 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002023 /* Obtain the value string */
2024 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002025 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002026
2027 /* Set tmp_end to end of the string */
2028 tmp_end = (char *) value + strlen(value);
2029
2030 /* Check if following character is the deliminator
2031 * If yes, we have encountered a double deliminator
2032 * reset the NULL character to the deliminator
2033 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302034 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002035 tmp_end[0] = delim;
2036
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302037 /* Keep iterating until we get to a single
2038 * deliminator OR the end
2039 */
2040 while ((tmp_end = strchr(tmp_end, delim))
2041 != NULL && (tmp_end[1] == delim)) {
2042 tmp_end = (char *) &tmp_end[2];
2043 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002044
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302045 /* Reset var options to point to next element */
2046 if (tmp_end) {
2047 tmp_end[0] = '\0';
2048 options = (char *) &tmp_end[1];
2049 } else
2050 /* Reached the end of the mount option
2051 * string */
2052 options = end;
2053 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002054
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002055 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002056 /* Now build new password string */
2057 temp_len = strlen(value);
2058 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2059 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002060 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002061 goto cifs_parse_mount_err;
2062 }
2063
2064 for (i = 0, j = 0; i < temp_len; i++, j++) {
2065 vol->password[j] = value[i];
2066 if ((value[i] == delim) &&
2067 value[i+1] == delim)
2068 /* skip the second deliminator */
2069 i++;
2070 }
2071 vol->password[j] = '\0';
2072 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002073 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002074 /* FIXME: should this be an error instead? */
2075 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002076 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002077 case Opt_ip:
2078 string = match_strdup(args);
2079 if (string == NULL)
2080 goto out_nomem;
2081
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002082 if (!cifs_convert_address(dstaddr, string,
2083 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002084 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002085 goto cifs_parse_mount_err;
2086 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002087 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002088 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002089 case Opt_domain:
2090 string = match_strdup(args);
2091 if (string == NULL)
2092 goto out_nomem;
2093
Chen Gang057d6332013-07-19 09:01:36 +08002094 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2095 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002096 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002097 goto cifs_parse_mount_err;
2098 }
2099
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002100 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002101 vol->domainname = kstrdup(string, GFP_KERNEL);
2102 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002103 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002104 goto cifs_parse_mount_err;
2105 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002106 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002107 break;
2108 case Opt_srcaddr:
2109 string = match_strdup(args);
2110 if (string == NULL)
2111 goto out_nomem;
2112
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002113 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002114 (struct sockaddr *)&vol->srcaddr,
2115 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002116 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2117 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002118 goto cifs_parse_mount_err;
2119 }
2120 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002121 case Opt_iocharset:
2122 string = match_strdup(args);
2123 if (string == NULL)
2124 goto out_nomem;
2125
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002126 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002127 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002128 goto cifs_parse_mount_err;
2129 }
2130
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002131 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002132 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002133 vol->iocharset = kstrdup(string,
2134 GFP_KERNEL);
2135 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002136 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002137 goto cifs_parse_mount_err;
2138 }
2139 }
2140 /* if iocharset not set then load_nls_default
2141 * is used by caller
2142 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002143 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002144 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002145 case Opt_netbiosname:
2146 string = match_strdup(args);
2147 if (string == NULL)
2148 goto out_nomem;
2149
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002150 memset(vol->source_rfc1001_name, 0x20,
2151 RFC1001_NAME_LEN);
2152 /*
2153 * FIXME: are there cases in which a comma can
2154 * be valid in workstation netbios name (and
2155 * need special handling)?
2156 */
2157 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2158 /* don't ucase netbiosname for user */
2159 if (string[i] == 0)
2160 break;
2161 vol->source_rfc1001_name[i] = string[i];
2162 }
2163 /* The string has 16th byte zero still from
2164 * set at top of the function
2165 */
2166 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002167 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002168 break;
2169 case Opt_servern:
2170 /* servernetbiosname specified override *SMBSERVER */
2171 string = match_strdup(args);
2172 if (string == NULL)
2173 goto out_nomem;
2174
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002175 /* last byte, type, is 0x20 for servr type */
2176 memset(vol->target_rfc1001_name, 0x20,
2177 RFC1001_NAME_LEN_WITH_NULL);
2178
2179 /* BB are there cases in which a comma can be
2180 valid in this workstation netbios name
2181 (and need special handling)? */
2182
2183 /* user or mount helper must uppercase the
2184 netbios name */
2185 for (i = 0; i < 15; i++) {
2186 if (string[i] == 0)
2187 break;
2188 vol->target_rfc1001_name[i] = string[i];
2189 }
2190 /* The string has 16th byte zero still from
2191 set at top of the function */
2192 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002193 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002194 break;
2195 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002196 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002197 string = match_strdup(args);
2198 if (string == NULL)
2199 goto out_nomem;
2200
Steve French7e682f72017-08-31 21:34:24 -05002201 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002202 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002203 if (strlen(string) > 1) {
2204 pr_warn("Bad mount helper ver=%s. Did "
2205 "you want SMB1 (CIFS) dialect "
2206 "and mean to type vers=1.0 "
2207 "instead?\n", string);
2208 goto cifs_parse_mount_err;
2209 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002210 /* This is the default */
2211 break;
2212 }
2213 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05002214 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002215 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002216 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002217 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002218 string = match_strdup(args);
2219 if (string == NULL)
2220 goto out_nomem;
2221
Steve Frenchc7c137b2018-06-06 17:59:29 -05002222 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002223 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002224 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002225 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002226 case Opt_sec:
2227 string = match_strdup(args);
2228 if (string == NULL)
2229 goto out_nomem;
2230
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002231 if (cifs_parse_security_flavors(string, vol) != 0)
2232 goto cifs_parse_mount_err;
2233 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002234 case Opt_cache:
2235 string = match_strdup(args);
2236 if (string == NULL)
2237 goto out_nomem;
2238
2239 if (cifs_parse_cache_flavor(string, vol) != 0)
2240 goto cifs_parse_mount_err;
2241 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002242 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002243 /*
2244 * An option we don't recognize. Save it off for later
2245 * if we haven't already found one
2246 */
2247 if (!invalid)
2248 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002249 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002251 /* Free up any allocated string */
2252 kfree(string);
2253 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002255
Jeff Laytond8162552012-03-23 14:40:56 -04002256 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002257 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002258 goto cifs_parse_mount_err;
2259 }
2260
Long Li8339dd32017-11-07 01:54:55 -07002261 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2262 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2263 goto cifs_parse_mount_err;
2264 }
2265
Jeff Layton8a8798a2012-01-17 16:09:15 -05002266#ifndef CONFIG_KEYS
2267 /* Muliuser mounts require CONFIG_KEYS support */
2268 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002269 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002270 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002271 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002272#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002273 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002274 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002275 goto cifs_parse_mount_err;
2276 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002277
Jeff Layton62a1a432012-12-10 06:10:45 -05002278 /* make sure UNC has a share name */
2279 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002280 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002281 goto cifs_parse_mount_err;
2282 }
2283
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002284 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002285 int len;
2286 const char *slash;
2287
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002288 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002289 /* Use the address part of the UNC. */
2290 slash = strchr(&vol->UNC[2], '\\');
2291 len = slash - &vol->UNC[2];
2292 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002293 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002294 goto cifs_parse_mount_err;
2295 }
2296 }
2297
2298 /* set the port that we got earlier */
2299 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002301 if (uid_specified)
2302 vol->override_uid = override_uid;
2303 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002304 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002305
2306 if (gid_specified)
2307 vol->override_gid = override_gid;
2308 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002309 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002310
Steve French7e682f72017-08-31 21:34:24 -05002311 if (got_version == false)
2312 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002313 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002314 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002315 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2316 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002317
Sean Finneyb9468452011-04-11 13:19:32 +00002318 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002320
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002321out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002322 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002323cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002324 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002325 kfree(mountdata_copy);
2326 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327}
2328
Ben Greear3eb9a882010-09-01 17:06:02 -07002329/** Returns true if srcaddr isn't specified and rhs isn't
2330 * specified, or if srcaddr is specified and
2331 * matches the IP address of the rhs argument.
2332 */
Jeff Layton45151482010-07-06 20:43:02 -04002333static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002334srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2335{
2336 switch (srcaddr->sa_family) {
2337 case AF_UNSPEC:
2338 return (rhs->sa_family == AF_UNSPEC);
2339 case AF_INET: {
2340 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2341 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2342 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2343 }
2344 case AF_INET6: {
2345 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002346 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002347 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2348 }
2349 default:
2350 WARN_ON(1);
2351 return false; /* don't expect to be here */
2352 }
2353}
2354
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002355/*
2356 * If no port is specified in addr structure, we try to match with 445 port
2357 * and if it fails - with 139 ports. It should be called only if address
2358 * families of server and addr are equal.
2359 */
2360static bool
2361match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2362{
Steve French6da97912011-03-13 18:55:55 +00002363 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002364
2365 switch (addr->sa_family) {
2366 case AF_INET:
2367 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2368 port = ((struct sockaddr_in *) addr)->sin_port;
2369 break;
2370 case AF_INET6:
2371 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2372 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2373 break;
2374 default:
2375 WARN_ON(1);
2376 return false;
2377 }
2378
2379 if (!port) {
2380 port = htons(CIFS_PORT);
2381 if (port == *sport)
2382 return true;
2383
2384 port = htons(RFC1001_PORT);
2385 }
2386
2387 return port == *sport;
2388}
Ben Greear3eb9a882010-09-01 17:06:02 -07002389
2390static bool
2391match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2392 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393{
Jeff Layton45151482010-07-06 20:43:02 -04002394 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002395 case AF_INET: {
2396 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2397 struct sockaddr_in *srv_addr4 =
2398 (struct sockaddr_in *)&server->dstaddr;
2399
2400 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002401 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002402 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002403 }
2404 case AF_INET6: {
2405 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2406 struct sockaddr_in6 *srv_addr6 =
2407 (struct sockaddr_in6 *)&server->dstaddr;
2408
Jeff Layton45151482010-07-06 20:43:02 -04002409 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002410 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002411 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002412 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002413 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002414 break;
2415 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002416 default:
2417 WARN_ON(1);
2418 return false; /* don't expect to be here */
2419 }
Jeff Layton45151482010-07-06 20:43:02 -04002420
Ben Greear3eb9a882010-09-01 17:06:02 -07002421 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2422 return false;
2423
Jeff Layton45151482010-07-06 20:43:02 -04002424 return true;
2425}
2426
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002427static bool
2428match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2429{
Jeff Layton3f618222013-06-12 19:52:14 -05002430 /*
2431 * The select_sectype function should either return the vol->sectype
2432 * that was specified, or "Unspecified" if that sectype was not
2433 * compatible with the given NEGOTIATE request.
2434 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302435 if (server->ops->select_sectype(server, vol->sectype)
2436 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002437 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002438
Jeff Layton3f618222013-06-12 19:52:14 -05002439 /*
2440 * Now check if signing mode is acceptable. No need to check
2441 * global_secflags at this point since if MUST_SIGN is set then
2442 * the server->sign had better be too.
2443 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002444 if (vol->sign && !server->sign)
2445 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002446
2447 return true;
2448}
2449
Jeff Layton9fa114f2012-11-26 11:09:57 -05002450static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002451{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002452 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2453
Jeff Laytona0b3df52013-05-24 07:40:59 -04002454 if (vol->nosharesock)
2455 return 0;
2456
Steve French9764c022017-09-17 10:41:35 -05002457 /* BB update this for smb3any and default case */
Jeff Layton23db65f2012-05-15 12:20:51 -04002458 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2459 return 0;
2460
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002461 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2462 return 0;
2463
2464 if (!match_address(server, addr,
2465 (struct sockaddr *)&vol->srcaddr))
2466 return 0;
2467
2468 if (!match_port(server, addr))
2469 return 0;
2470
2471 if (!match_security(server, vol))
2472 return 0;
2473
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002474 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002475 return 0;
2476
Long Li8339dd32017-11-07 01:54:55 -07002477 if (server->rdma != vol->rdma)
2478 return 0;
2479
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002480 return 1;
2481}
2482
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002483struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002484cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002485{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002486 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302488 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002489 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002490 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002491 continue;
2492
Jeff Laytone7ddee92008-11-14 13:44:38 -05002493 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302494 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002495 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002496 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302498 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 return NULL;
2500}
2501
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002502void
2503cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002505 struct task_struct *task;
2506
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302507 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002508 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302509 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002510 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002512
Rob Landleyf1d0c992011-01-22 15:44:05 -06002513 put_net(cifs_net_ns(server));
2514
Jeff Laytone7ddee92008-11-14 13:44:38 -05002515 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302516 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002517
Jeff Laytonc74093b2011-01-11 07:24:23 -05002518 cancel_delayed_work_sync(&server->echo);
2519
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002520 if (from_reconnect)
2521 /*
2522 * Avoid deadlock here: reconnect work calls
2523 * cifs_put_tcp_session() at its end. Need to be sure
2524 * that reconnect work does nothing with server pointer after
2525 * that step.
2526 */
2527 cancel_delayed_work(&server->reconnect);
2528 else
2529 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002530
Jeff Laytone7ddee92008-11-14 13:44:38 -05002531 spin_lock(&GlobalMid_Lock);
2532 server->tcpStatus = CifsExiting;
2533 spin_unlock(&GlobalMid_Lock);
2534
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002535 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302536 cifs_fscache_release_client_cookie(server);
2537
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002538 kfree(server->session_key.response);
2539 server->session_key.response = NULL;
2540 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002541
2542 task = xchg(&server->tsk, NULL);
2543 if (task)
2544 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545}
2546
Jeff Layton63c038c2008-12-01 18:41:46 -05002547static struct TCP_Server_Info *
2548cifs_get_tcp_session(struct smb_vol *volume_info)
2549{
2550 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002551 int rc;
2552
Joe Perchesf96637b2013-05-04 22:12:25 -05002553 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002554
2555 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002556 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002557 if (tcp_ses)
2558 return tcp_ses;
2559
2560 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2561 if (!tcp_ses) {
2562 rc = -ENOMEM;
2563 goto out_err;
2564 }
2565
Jeff Layton23db65f2012-05-15 12:20:51 -04002566 tcp_ses->ops = volume_info->ops;
2567 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002568 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002569 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2570 if (IS_ERR(tcp_ses->hostname)) {
2571 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002572 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002573 }
2574
2575 tcp_ses->noblocksnd = volume_info->noblocksnd;
2576 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002577 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002578 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002579 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002580 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002581 init_waitqueue_head(&tcp_ses->response_q);
2582 init_waitqueue_head(&tcp_ses->request_q);
2583 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2584 mutex_init(&tcp_ses->srv_mutex);
2585 memcpy(tcp_ses->workstation_RFC1001_name,
2586 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2587 memcpy(tcp_ses->server_RFC1001_name,
2588 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002589 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002590 tcp_ses->sequence_number = 0;
Steve French9e1a37d2018-09-19 02:38:17 -05002591 tcp_ses->reconnect_instance = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002592 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002593 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002594 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2595 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002596 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002597 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2598 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002599 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2600 sizeof(tcp_ses->srcaddr));
2601 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2602 sizeof(tcp_ses->dstaddr));
Steve Frenchfa70b872016-09-22 00:39:34 -05002603 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002604 /*
2605 * at this point we are the only ones with the pointer
2606 * to the struct since the kernel thread not created yet
2607 * no need to spinlock this init of tcpStatus or srv_count
2608 */
2609 tcp_ses->tcpStatus = CifsNew;
2610 ++tcp_ses->srv_count;
2611
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002612 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2613 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2614 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2615 else
2616 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002617 if (tcp_ses->rdma) {
2618#ifndef CONFIG_CIFS_SMB_DIRECT
2619 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2620 rc = -ENOENT;
2621 goto out_err_crypto_release;
2622#endif
2623 tcp_ses->smbd_conn = smbd_get_connection(
2624 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2625 if (tcp_ses->smbd_conn) {
2626 cifs_dbg(VFS, "RDMA transport established\n");
2627 rc = 0;
2628 goto smbd_connected;
2629 } else {
2630 rc = -ENOENT;
2631 goto out_err_crypto_release;
2632 }
2633 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002634 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002635 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002636 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002637 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002638 }
Long Li2f894642017-11-22 17:38:34 -07002639smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002640 /*
2641 * since we're in a cifs function already, we know that
2642 * this will succeed. No need for try_module_get().
2643 */
2644 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002645 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002646 tcp_ses, "cifsd");
2647 if (IS_ERR(tcp_ses->tsk)) {
2648 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002649 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002650 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002651 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002652 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002653 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002654
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002655 tcp_ses->nr_targets = 1;
2656
Jeff Layton63c038c2008-12-01 18:41:46 -05002657 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302658 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002659 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302660 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002661
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302662 cifs_fscache_get_client_cookie(tcp_ses);
2663
Jeff Laytonc74093b2011-01-11 07:24:23 -05002664 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002665 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002666
Jeff Layton63c038c2008-12-01 18:41:46 -05002667 return tcp_ses;
2668
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002669out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002670 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002671
Rob Landleyf1d0c992011-01-22 15:44:05 -06002672 put_net(cifs_net_ns(tcp_ses));
2673
Jeff Layton63c038c2008-12-01 18:41:46 -05002674out_err:
2675 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002676 if (!IS_ERR(tcp_ses->hostname))
2677 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002678 if (tcp_ses->ssocket)
2679 sock_release(tcp_ses->ssocket);
2680 kfree(tcp_ses);
2681 }
2682 return ERR_PTR(rc);
2683}
2684
Steve French96daf2b2011-05-27 04:34:02 +00002685static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002686{
Jeff Layton3f618222013-06-12 19:52:14 -05002687 if (vol->sectype != Unspecified &&
2688 vol->sectype != ses->sectype)
2689 return 0;
2690
2691 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002692 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002693 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002694 return 0;
2695 break;
2696 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002697 /* NULL username means anonymous session */
2698 if (ses->user_name == NULL) {
2699 if (!vol->nullauth)
2700 return 0;
2701 break;
2702 }
2703
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002704 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002705 if (strncmp(ses->user_name,
2706 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002707 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002708 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002709 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002710 ses->password != NULL &&
2711 strncmp(ses->password,
2712 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002713 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002714 return 0;
2715 }
2716 return 1;
2717}
2718
Aurelien Aptelb327a712018-01-24 13:46:10 +01002719/**
2720 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2721 *
2722 * A new IPC connection is made and stored in the session
2723 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2724 */
2725static int
2726cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2727{
2728 int rc = 0, xid;
2729 struct cifs_tcon *tcon;
2730 struct nls_table *nls_codepage;
2731 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2732 bool seal = false;
2733
2734 /*
2735 * If the mount request that resulted in the creation of the
2736 * session requires encryption, force IPC to be encrypted too.
2737 */
2738 if (volume_info->seal) {
2739 if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
2740 seal = true;
2741 else {
2742 cifs_dbg(VFS,
2743 "IPC: server doesn't support encryption\n");
2744 return -EOPNOTSUPP;
2745 }
2746 }
2747
2748 tcon = tconInfoAlloc();
2749 if (tcon == NULL)
2750 return -ENOMEM;
2751
Thomas Werschlein395a2072018-08-30 18:29:20 +02002752 snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002753
2754 /* cannot fail */
2755 nls_codepage = load_nls_default();
2756
2757 xid = get_xid();
2758 tcon->ses = ses;
2759 tcon->ipc = true;
2760 tcon->seal = seal;
2761 rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
2762 free_xid(xid);
2763
2764 if (rc) {
2765 cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
2766 tconInfoFree(tcon);
2767 goto out;
2768 }
2769
2770 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2771
2772 ses->tcon_ipc = tcon;
2773out:
2774 unload_nls(nls_codepage);
2775 return rc;
2776}
2777
2778/**
2779 * cifs_free_ipc - helper to release the session IPC tcon
2780 *
2781 * Needs to be called everytime a session is destroyed
2782 */
2783static int
2784cifs_free_ipc(struct cifs_ses *ses)
2785{
2786 int rc = 0, xid;
2787 struct cifs_tcon *tcon = ses->tcon_ipc;
2788
2789 if (tcon == NULL)
2790 return 0;
2791
2792 if (ses->server->ops->tree_disconnect) {
2793 xid = get_xid();
2794 rc = ses->server->ops->tree_disconnect(xid, tcon);
2795 free_xid(xid);
2796 }
2797
2798 if (rc)
2799 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
2800
2801 tconInfoFree(tcon);
2802 ses->tcon_ipc = NULL;
2803 return rc;
2804}
2805
Steve French96daf2b2011-05-27 04:34:02 +00002806static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002807cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808{
Steve French96daf2b2011-05-27 04:34:02 +00002809 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302811 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002812 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002813 if (ses->status == CifsExiting)
2814 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002815 if (!match_session(ses, vol))
2816 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002817 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302818 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002819 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302821 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 return NULL;
2823}
2824
Jeff Layton14fbf502008-11-14 13:53:46 -05002825static void
Steve French96daf2b2011-05-27 04:34:02 +00002826cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002827{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002828 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002829 struct TCP_Server_Info *server = ses->server;
2830
Joe Perchesf96637b2013-05-04 22:12:25 -05002831 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002832
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302833 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002834 if (ses->status == CifsExiting) {
2835 spin_unlock(&cifs_tcp_ses_lock);
2836 return;
2837 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002838 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302839 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002840 return;
2841 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002842 if (ses->status == CifsGood)
2843 ses->status = CifsExiting;
2844 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002845
Aurelien Aptelb327a712018-01-24 13:46:10 +01002846 cifs_free_ipc(ses);
2847
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002848 if (ses->status == CifsExiting && server->ops->logoff) {
2849 xid = get_xid();
2850 rc = server->ops->logoff(xid, ses);
2851 if (rc)
2852 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2853 __func__, rc);
2854 _free_xid(xid);
2855 }
2856
2857 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002858 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302859 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002860
Jeff Layton14fbf502008-11-14 13:53:46 -05002861 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002862 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05002863}
2864
Jeff Layton8a8798a2012-01-17 16:09:15 -05002865#ifdef CONFIG_KEYS
2866
Chen Gang057d6332013-07-19 09:01:36 +08002867/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2868#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002869
2870/* Populate username and pw fields from keyring if possible */
2871static int
2872cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2873{
2874 int rc = 0;
David Howells146aa8b2015-10-21 14:04:48 +01002875 const char *delim, *payload;
2876 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002877 ssize_t len;
2878 struct key *key;
2879 struct TCP_Server_Info *server = ses->server;
2880 struct sockaddr_in *sa;
2881 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01002882 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002883
2884 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2885 if (!desc)
2886 return -ENOMEM;
2887
2888 /* try to find an address key first */
2889 switch (server->dstaddr.ss_family) {
2890 case AF_INET:
2891 sa = (struct sockaddr_in *)&server->dstaddr;
2892 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2893 break;
2894 case AF_INET6:
2895 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2896 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2897 break;
2898 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002899 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2900 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002901 rc = -EINVAL;
2902 goto out_err;
2903 }
2904
Joe Perchesf96637b2013-05-04 22:12:25 -05002905 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002906 key = request_key(&key_type_logon, desc, "");
2907 if (IS_ERR(key)) {
2908 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002909 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002910 rc = PTR_ERR(key);
2911 goto out_err;
2912 }
2913
2914 /* didn't work, try to find a domain key */
2915 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002916 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002917 key = request_key(&key_type_logon, desc, "");
2918 if (IS_ERR(key)) {
2919 rc = PTR_ERR(key);
2920 goto out_err;
2921 }
2922 }
2923
2924 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00002925 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002926 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002927 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002928 goto out_key_put;
2929 }
2930
2931 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01002932 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002933 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002934 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002935 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002936 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2937 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002938 rc = -EINVAL;
2939 goto out_key_put;
2940 }
2941
2942 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002943 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002944 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2945 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002946 rc = -EINVAL;
2947 goto out_key_put;
2948 }
2949
2950 vol->username = kstrndup(payload, len, GFP_KERNEL);
2951 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002952 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2953 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002954 rc = -ENOMEM;
2955 goto out_key_put;
2956 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002957 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002958
2959 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002960 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002961 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002962 rc = -EINVAL;
2963 kfree(vol->username);
2964 vol->username = NULL;
2965 goto out_key_put;
2966 }
2967
2968 ++delim;
2969 vol->password = kstrndup(delim, len, GFP_KERNEL);
2970 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002971 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2972 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002973 rc = -ENOMEM;
2974 kfree(vol->username);
2975 vol->username = NULL;
2976 goto out_key_put;
2977 }
2978
2979out_key_put:
2980 up_read(&key->sem);
2981 key_put(key);
2982out_err:
2983 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002984 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002985 return rc;
2986}
2987#else /* ! CONFIG_KEYS */
2988static inline int
2989cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2990 struct cifs_ses *ses __attribute__((unused)))
2991{
2992 return -ENOSYS;
2993}
2994#endif /* CONFIG_KEYS */
2995
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002996/**
2997 * cifs_get_smb_ses - get a session matching @volume_info data from @server
2998 *
2999 * This function assumes it is being called from cifs_mount() where we
3000 * already got a server reference (server refcount +1). See
3001 * cifs_get_tcon() for refcount explanations.
3002 */
Steve French96daf2b2011-05-27 04:34:02 +00003003static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04003004cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3005{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003006 int rc = -ENOMEM;
3007 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003008 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003009 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3010 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04003011
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003012 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04003013
Jeff Layton4ff67b72010-07-06 20:43:02 -04003014 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04003015 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003016 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3017 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04003018
Jeff Layton36988c72010-04-24 07:57:43 -04003019 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003020 rc = cifs_negotiate_protocol(xid, ses);
3021 if (rc) {
3022 mutex_unlock(&ses->session_mutex);
3023 /* problem -- put our ses reference */
3024 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003025 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003026 return ERR_PTR(rc);
3027 }
Jeff Layton36988c72010-04-24 07:57:43 -04003028 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003029 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003030 rc = cifs_setup_session(xid, ses,
3031 volume_info->local_nls);
3032 if (rc) {
3033 mutex_unlock(&ses->session_mutex);
3034 /* problem -- put our reference */
3035 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003036 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003037 return ERR_PTR(rc);
3038 }
3039 }
3040 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003041
3042 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003043 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003044 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003045 return ses;
3046 }
3047
Joe Perchesf96637b2013-05-04 22:12:25 -05003048 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003049 ses = sesInfoAlloc();
3050 if (ses == NULL)
3051 goto get_ses_fail;
3052
3053 /* new SMB session uses our server ref */
3054 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003055 if (server->dstaddr.ss_family == AF_INET6)
3056 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003057 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003058 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003059
Steve French8727c8a2011-02-25 01:11:56 -06003060 if (volume_info->username) {
3061 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3062 if (!ses->user_name)
3063 goto get_ses_fail;
3064 }
Jeff Layton36988c72010-04-24 07:57:43 -04003065
3066 /* volume_info->password freed at unmount */
3067 if (volume_info->password) {
3068 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3069 if (!ses->password)
3070 goto get_ses_fail;
3071 }
3072 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003073 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3074 if (!ses->domainName)
3075 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003076 }
Germano Percossi39566442016-12-15 12:31:18 +05303077 if (volume_info->domainauto)
3078 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003079 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003080 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003081
Jeff Layton28e11bd2013-05-26 07:01:00 -04003082 ses->sectype = volume_info->sectype;
3083 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003084
3085 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003086 rc = cifs_negotiate_protocol(xid, ses);
3087 if (!rc)
3088 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04003089 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003090 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003091 goto get_ses_fail;
3092
3093 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303094 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003095 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303096 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003097
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003098 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003099
3100 cifs_setup_ipc(ses, volume_info);
3101
Jeff Layton36988c72010-04-24 07:57:43 -04003102 return ses;
3103
3104get_ses_fail:
3105 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003106 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003107 return ERR_PTR(rc);
3108}
3109
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003110static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003111{
3112 if (tcon->tidStatus == CifsExiting)
3113 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003114 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003115 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003116 if (tcon->seal != volume_info->seal)
3117 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003118 if (tcon->snapshot_time != volume_info->snapshot_time)
3119 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003120 return 1;
3121}
3122
Steve French96daf2b2011-05-27 04:34:02 +00003123static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003124cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125{
3126 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003127 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303129 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003130 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003131 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003132 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003133 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003134 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303135 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 return tcon;
3137 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303138 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 return NULL;
3140}
3141
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003142void
Steve French96daf2b2011-05-27 04:34:02 +00003143cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003144{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003145 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003146 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003147
Aurelien Aptelb327a712018-01-24 13:46:10 +01003148 /*
3149 * IPC tcon share the lifetime of their session and are
3150 * destroyed in the session put function
3151 */
3152 if (tcon == NULL || tcon->ipc)
3153 return;
3154
3155 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003156 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303157 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003158 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303159 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003160 return;
3161 }
3162
3163 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303164 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003165
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003166 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003167 if (ses->server->ops->tree_disconnect)
3168 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003169 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003170
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303171 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003172 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003173 cifs_put_smb_ses(ses);
3174}
3175
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003176/**
3177 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3178 *
3179 * - tcon refcount is the number of mount points using the tcon.
3180 * - ses refcount is the number of tcon using the session.
3181 *
3182 * 1. This function assumes it is being called from cifs_mount() where
3183 * we already got a session reference (ses refcount +1).
3184 *
3185 * 2. Since we're in the context of adding a mount point, the end
3186 * result should be either:
3187 *
3188 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3189 * its session refcount incremented (1 new tcon). This +1 was
3190 * already done in (1).
3191 *
3192 * b) an existing tcon with refcount+1 (add a mount point to it) and
3193 * identical ses refcount (no new tcon). Because of (1) we need to
3194 * decrement the ses refcount.
3195 */
Steve French96daf2b2011-05-27 04:34:02 +00003196static struct cifs_tcon *
3197cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003198{
3199 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003200 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003201
Steve French8b217fe2016-11-11 22:36:20 -06003202 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003203 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003204 /*
3205 * tcon has refcount already incremented but we need to
3206 * decrement extra ses reference gotten by caller (case b)
3207 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003208 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003209 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003210 return tcon;
3211 }
3212
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003213 if (!ses->server->ops->tree_connect) {
3214 rc = -ENOSYS;
3215 goto out_fail;
3216 }
3217
Jeff Laytond00c28d2010-04-24 07:57:44 -04003218 tcon = tconInfoAlloc();
3219 if (tcon == NULL) {
3220 rc = -ENOMEM;
3221 goto out_fail;
3222 }
3223
Steve French8b217fe2016-11-11 22:36:20 -06003224 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003225 if (ses->server->vals->protocol_id == 0) {
3226 cifs_dbg(VFS,
3227 "Use SMB2 or later for snapshot mount option\n");
3228 rc = -EOPNOTSUPP;
3229 goto out_fail;
3230 } else
3231 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003232 }
3233
Jeff Laytond00c28d2010-04-24 07:57:44 -04003234 tcon->ses = ses;
3235 if (volume_info->password) {
3236 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3237 if (!tcon->password) {
3238 rc = -ENOMEM;
3239 goto out_fail;
3240 }
3241 }
3242
Steve French23657ad2018-04-22 15:14:58 -05003243 if (volume_info->seal) {
3244 if (ses->server->vals->protocol_id == 0) {
3245 cifs_dbg(VFS,
3246 "SMB3 or later required for encryption\n");
3247 rc = -EOPNOTSUPP;
3248 goto out_fail;
3249 } else if (tcon->ses->server->capabilities &
3250 SMB2_GLOBAL_CAP_ENCRYPTION)
3251 tcon->seal = true;
3252 else {
3253 cifs_dbg(VFS, "Encryption is not supported on share\n");
3254 rc = -EOPNOTSUPP;
3255 goto out_fail;
3256 }
3257 }
3258
Steve French8505c8b2018-06-18 14:01:59 -05003259 if (volume_info->linux_ext) {
3260 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003261 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003262 printk_once(KERN_WARNING
3263 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003264 } else {
3265 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3266 rc = -EOPNOTSUPP;
3267 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003268 }
Steve Frenchb3266142018-05-20 23:41:10 -05003269 }
Steve Frenchb3266142018-05-20 23:41:10 -05003270
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003271 /*
3272 * BB Do we need to wrap session_mutex around this TCon call and Unix
3273 * SetFS as we do on SessSetup and reconnect?
3274 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003275 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003276 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3277 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003278 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003279 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003280 if (rc)
3281 goto out_fail;
3282
Steve Frenchb618f002015-11-03 09:15:03 -06003283 tcon->use_persistent = false;
3284 /* check if SMB2 or later, CIFS does not support persistent handles */
3285 if (volume_info->persistent) {
3286 if (ses->server->vals->protocol_id == 0) {
3287 cifs_dbg(VFS,
3288 "SMB3 or later required for persistent handles\n");
3289 rc = -EOPNOTSUPP;
3290 goto out_fail;
3291 } else if (ses->server->capabilities &
3292 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3293 tcon->use_persistent = true;
3294 else /* persistent handles requested but not supported */ {
3295 cifs_dbg(VFS,
3296 "Persistent handles not supported on share\n");
3297 rc = -EOPNOTSUPP;
3298 goto out_fail;
3299 }
3300 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3301 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3302 && (volume_info->nopersistent == false)) {
3303 cifs_dbg(FYI, "enabling persistent handles\n");
3304 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003305 } else if (volume_info->resilient) {
3306 if (ses->server->vals->protocol_id == 0) {
3307 cifs_dbg(VFS,
3308 "SMB2.1 or later required for resilient handles\n");
3309 rc = -EOPNOTSUPP;
3310 goto out_fail;
3311 }
3312 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003313 }
3314
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003315 /*
3316 * We can have only one retry value for a connection to a share so for
3317 * resources mounted more than once to the same server share the last
3318 * value passed in for the retry flag is used.
3319 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003320 tcon->retry = volume_info->retry;
3321 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003322 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003323 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003324 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003325
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303326 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003327 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303328 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003329
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303330 cifs_fscache_get_super_cookie(tcon);
3331
Jeff Laytond00c28d2010-04-24 07:57:44 -04003332 return tcon;
3333
3334out_fail:
3335 tconInfoFree(tcon);
3336 return ERR_PTR(rc);
3337}
3338
Jeff Layton9d002df2010-10-06 19:51:11 -04003339void
3340cifs_put_tlink(struct tcon_link *tlink)
3341{
3342 if (!tlink || IS_ERR(tlink))
3343 return;
3344
3345 if (!atomic_dec_and_test(&tlink->tl_count) ||
3346 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3347 tlink->tl_time = jiffies;
3348 return;
3349 }
3350
3351 if (!IS_ERR(tlink_tcon(tlink)))
3352 cifs_put_tcon(tlink_tcon(tlink));
3353 kfree(tlink);
3354 return;
3355}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003356
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003357static int
3358compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3359{
3360 struct cifs_sb_info *old = CIFS_SB(sb);
3361 struct cifs_sb_info *new = mnt_data->cifs_sb;
3362
3363 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3364 return 0;
3365
3366 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
3367 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
3368 return 0;
3369
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003370 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003371 * We want to share sb only if we don't specify an r/wsize or
3372 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003373 */
3374 if (new->wsize && new->wsize < old->wsize)
3375 return 0;
3376
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003377 if (new->rsize && new->rsize < old->rsize)
3378 return 0;
3379
Eric W. Biederman1f682332013-02-06 01:20:20 -08003380 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003381 return 0;
3382
3383 if (old->mnt_file_mode != new->mnt_file_mode ||
3384 old->mnt_dir_mode != new->mnt_dir_mode)
3385 return 0;
3386
3387 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3388 return 0;
3389
3390 if (old->actimeo != new->actimeo)
3391 return 0;
3392
3393 return 1;
3394}
3395
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003396static int
3397match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3398{
3399 struct cifs_sb_info *old = CIFS_SB(sb);
3400 struct cifs_sb_info *new = mnt_data->cifs_sb;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003401 bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3402 bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003403
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003404 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003405 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003406 else if (!old_set && !new_set)
3407 return 1;
3408
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003409 return 0;
3410}
3411
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003412int
3413cifs_match_super(struct super_block *sb, void *data)
3414{
3415 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3416 struct smb_vol *volume_info;
3417 struct cifs_sb_info *cifs_sb;
3418 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003419 struct cifs_ses *ses;
3420 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003421 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003422 int rc = 0;
3423
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003424 spin_lock(&cifs_tcp_ses_lock);
3425 cifs_sb = CIFS_SB(sb);
3426 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3427 if (IS_ERR(tlink)) {
3428 spin_unlock(&cifs_tcp_ses_lock);
3429 return rc;
3430 }
3431 tcon = tlink_tcon(tlink);
3432 ses = tcon->ses;
3433 tcp_srv = ses->server;
3434
3435 volume_info = mnt_data->vol;
3436
Jeff Layton9fa114f2012-11-26 11:09:57 -05003437 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003438 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003439 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003440 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003441 rc = 0;
3442 goto out;
3443 }
3444
3445 rc = compare_mount_options(sb, mnt_data);
3446out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003447 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003448 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003449 return rc;
3450}
3451
Jeff Layton09e50d52008-07-23 10:11:19 -04003452#ifdef CONFIG_DEBUG_LOCK_ALLOC
3453static struct lock_class_key cifs_key[2];
3454static struct lock_class_key cifs_slock_key[2];
3455
3456static inline void
3457cifs_reclassify_socket4(struct socket *sock)
3458{
3459 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003460 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003461 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3462 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3463}
3464
3465static inline void
3466cifs_reclassify_socket6(struct socket *sock)
3467{
3468 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003469 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003470 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3471 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3472}
3473#else
3474static inline void
3475cifs_reclassify_socket4(struct socket *sock)
3476{
3477}
3478
3479static inline void
3480cifs_reclassify_socket6(struct socket *sock)
3481{
3482}
3483#endif
3484
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003486static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487{
Steve French50c2f752007-07-13 00:33:32 +00003488 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489
Steve French50c2f752007-07-13 00:33:32 +00003490 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491 /* mask a nibble at a time and encode */
3492 target[j] = 'A' + (0x0F & (source[i] >> 4));
3493 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003494 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495 }
3496
3497}
3498
Ben Greear3eb9a882010-09-01 17:06:02 -07003499static int
3500bind_socket(struct TCP_Server_Info *server)
3501{
3502 int rc = 0;
3503 if (server->srcaddr.ss_family != AF_UNSPEC) {
3504 /* Bind to the specified local IP address */
3505 struct socket *socket = server->ssocket;
3506 rc = socket->ops->bind(socket,
3507 (struct sockaddr *) &server->srcaddr,
3508 sizeof(server->srcaddr));
3509 if (rc < 0) {
3510 struct sockaddr_in *saddr4;
3511 struct sockaddr_in6 *saddr6;
3512 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3513 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3514 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05003515 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3516 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003517 else
Joe Perchesf96637b2013-05-04 22:12:25 -05003518 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3519 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003520 }
3521 }
3522 return rc;
3523}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524
3525static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003526ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527{
3528 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003529 /*
3530 * some servers require RFC1001 sessinit before sending
3531 * negprot - BB check reconnection in case where second
3532 * sessinit is sent but no second negprot
3533 */
3534 struct rfc1002_session_packet *ses_init_buf;
3535 struct smb_hdr *smb_buf;
3536 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3537 GFP_KERNEL);
3538 if (ses_init_buf) {
3539 ses_init_buf->trailer.session_req.called_len = 32;
3540
Colin Ian King997152f2016-01-25 16:25:54 +00003541 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003542 rfc1002mangle(ses_init_buf->trailer.
3543 session_req.called_name,
3544 server->server_RFC1001_name,
3545 RFC1001_NAME_LEN_WITH_NULL);
3546 else
3547 rfc1002mangle(ses_init_buf->trailer.
3548 session_req.called_name,
3549 DEFAULT_CIFS_CALLED_NAME,
3550 RFC1001_NAME_LEN_WITH_NULL);
3551
3552 ses_init_buf->trailer.session_req.calling_len = 32;
3553
3554 /*
3555 * calling name ends in null (byte 16) from old smb
3556 * convention.
3557 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003558 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003559 rfc1002mangle(ses_init_buf->trailer.
3560 session_req.calling_name,
3561 server->workstation_RFC1001_name,
3562 RFC1001_NAME_LEN_WITH_NULL);
3563 else
3564 rfc1002mangle(ses_init_buf->trailer.
3565 session_req.calling_name,
3566 "LINUX_CIFS_CLNT",
3567 RFC1001_NAME_LEN_WITH_NULL);
3568
3569 ses_init_buf->trailer.session_req.scope1 = 0;
3570 ses_init_buf->trailer.session_req.scope2 = 0;
3571 smb_buf = (struct smb_hdr *)ses_init_buf;
3572
3573 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003574 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003575 rc = smb_send(server, smb_buf, 0x44);
3576 kfree(ses_init_buf);
3577 /*
3578 * RFC1001 layer in at least one server
3579 * requires very short break before negprot
3580 * presumably because not expecting negprot
3581 * to follow so fast. This is a simple
3582 * solution that works without
3583 * complicating the code and causes no
3584 * significant slowing down on mount
3585 * for everyone else
3586 */
3587 usleep_range(1000, 2000);
3588 }
3589 /*
3590 * else the negprot may still work without this
3591 * even though malloc failed
3592 */
3593
3594 return rc;
3595}
3596
3597static int
3598generic_ip_connect(struct TCP_Server_Info *server)
3599{
3600 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003601 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003602 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003603 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003604 struct sockaddr *saddr;
3605
3606 saddr = (struct sockaddr *) &server->dstaddr;
3607
3608 if (server->dstaddr.ss_family == AF_INET6) {
3609 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3610 slen = sizeof(struct sockaddr_in6);
3611 sfamily = AF_INET6;
3612 } else {
3613 sport = ((struct sockaddr_in *) saddr)->sin_port;
3614 slen = sizeof(struct sockaddr_in);
3615 sfamily = AF_INET;
3616 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003618 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003619 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3620 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003622 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003623 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003626
3627 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003628 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003629 server->ssocket = socket;
3630 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003631 if (sfamily == AF_INET6)
3632 cifs_reclassify_socket6(socket);
3633 else
3634 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 }
3636
Ben Greear3eb9a882010-09-01 17:06:02 -07003637 rc = bind_socket(server);
3638 if (rc < 0)
3639 return rc;
3640
Jeff Laytond5c56052008-12-01 18:42:33 -05003641 /*
3642 * Eventually check for other socket options to change from
3643 * the default. sock_setsockopt not used because it expects
3644 * user space buffer
3645 */
3646 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003647 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003648
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003649 /* make the bufsizes depend on wsize/rsize and max requests */
3650 if (server->noautotune) {
3651 if (socket->sk->sk_sndbuf < (200 * 1024))
3652 socket->sk->sk_sndbuf = 200 * 1024;
3653 if (socket->sk->sk_rcvbuf < (140 * 1024))
3654 socket->sk->sk_rcvbuf = 140 * 1024;
3655 }
3656
Steve French6a5fa2362010-01-01 01:28:43 +00003657 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003658 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003659 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3660 (char *)&val, sizeof(val));
3661 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003662 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3663 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003664 }
3665
Joe Perchesf96637b2013-05-04 22:12:25 -05003666 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003667 socket->sk->sk_sndbuf,
3668 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3669
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003670 rc = socket->ops->connect(socket, saddr, slen, 0);
3671 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003672 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003673 sock_release(socket);
3674 server->ssocket = NULL;
3675 return rc;
3676 }
3677
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003678 if (sport == htons(RFC1001_PORT))
3679 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003680
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681 return rc;
3682}
3683
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003684static int
3685ip_connect(struct TCP_Server_Info *server)
3686{
Steve French6da97912011-03-13 18:55:55 +00003687 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003688 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3689 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3690
3691 if (server->dstaddr.ss_family == AF_INET6)
3692 sport = &addr6->sin6_port;
3693 else
3694 sport = &addr->sin_port;
3695
3696 if (*sport == 0) {
3697 int rc;
3698
3699 /* try with 445 port at first */
3700 *sport = htons(CIFS_PORT);
3701
3702 rc = generic_ip_connect(server);
3703 if (rc >= 0)
3704 return rc;
3705
3706 /* if it failed, try with 139 port */
3707 *sport = htons(RFC1001_PORT);
3708 }
3709
3710 return generic_ip_connect(server);
3711}
3712
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003713void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003714 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003715{
3716 /* if we are reconnecting then should we check to see if
3717 * any requested capabilities changed locally e.g. via
3718 * remount but we can not do much about it here
3719 * if they have (even if we could detect it by the following)
3720 * Perhaps we could add a backpointer to array of sb from tcon
3721 * or if we change to make all sb to same share the same
3722 * sb as NFS - then we only have one backpointer to sb.
3723 * What if we wanted to mount the server share twice once with
3724 * and once without posixacls or posix paths? */
3725 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003726
Steve Frenchc18c8422007-07-18 23:21:09 +00003727 if (vol_info && vol_info->no_linux_ext) {
3728 tcon->fsUnixInfo.Capability = 0;
3729 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003730 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003731 return;
3732 } else if (vol_info)
3733 tcon->unix_ext = 1; /* Unix Extensions supported */
3734
3735 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003736 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003737 return;
3738 }
Steve French50c2f752007-07-13 00:33:32 +00003739
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003740 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003741 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003742 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003743 /* check for reconnect case in which we do not
3744 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003745 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003746 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003747 originally at mount time */
3748 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3749 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003750 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3751 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003752 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003753 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003754 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003755 cifs_dbg(VFS, "possible reconnect error\n");
3756 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003757 }
Steve French8af18972007-02-14 04:42:51 +00003758 }
Steve French50c2f752007-07-13 00:33:32 +00003759
Steve French6848b732011-05-26 18:38:54 +00003760 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003761 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003762
Steve French8af18972007-02-14 04:42:51 +00003763 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003764 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003765 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003766 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003767 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003768 if (cifs_sb)
3769 cifs_sb->mnt_cifs_flags |=
3770 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003771 }
3772
Steve French75865f8c2007-06-24 18:30:48 +00003773 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003774 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003775 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003776 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003777 if (cifs_sb)
3778 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003779 CIFS_MOUNT_POSIX_PATHS;
3780 }
Steve French50c2f752007-07-13 00:33:32 +00003781
Joe Perchesf96637b2013-05-04 22:12:25 -05003782 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003783#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003784 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003785 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003786 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003787 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003788 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003789 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003790 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003791 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003792 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003793 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003794 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003795 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003796 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003797 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003798 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003799 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003800 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003801 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003802#endif /* CIFS_DEBUG2 */
3803 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003804 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003805 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003806 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003807 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 +00003808
Steve French8af18972007-02-14 04:42:51 +00003809 }
3810 }
3811}
3812
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003813int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003814 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003815{
Jeff Layton2de970f2010-10-06 19:51:12 -04003816 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3817
Al Viro2ced6f62011-06-17 09:20:04 -04003818 spin_lock_init(&cifs_sb->tlink_tree_lock);
3819 cifs_sb->tlink_tree = RB_ROOT;
3820
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003821 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003822 * Temporarily set r/wsize for matching superblock. If we end up using
3823 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003824 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003825 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003826 cifs_sb->wsize = pvolume_info->wsize;
3827
Steve French3b795212008-11-13 19:45:32 +00003828 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3829 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3830 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3831 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003832 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3833 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003834
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303835 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003836 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303837
Aurelien Aptel83930722018-09-20 18:10:25 -07003838 if (pvolume_info->nodfs)
3839 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00003840 if (pvolume_info->noperm)
3841 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3842 if (pvolume_info->setuids)
3843 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05003844 if (pvolume_info->setuidfromacl)
3845 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00003846 if (pvolume_info->server_ino)
3847 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3848 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003849 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3850 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003851 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3852 if (pvolume_info->no_xattr)
3853 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3854 if (pvolume_info->sfu_emul)
3855 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3856 if (pvolume_info->nobrl)
3857 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05003858 if (pvolume_info->nohandlecache)
3859 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00003860 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003861 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003862 if (pvolume_info->mand_lock)
3863 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003864 if (pvolume_info->rwpidforward)
3865 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003866 if (pvolume_info->cifs_acl)
3867 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003868 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003869 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003870 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3871 }
3872 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003873 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003874 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3875 }
Steve French3b795212008-11-13 19:45:32 +00003876 if (pvolume_info->override_uid)
3877 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3878 if (pvolume_info->override_gid)
3879 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3880 if (pvolume_info->dynperm)
3881 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303882 if (pvolume_info->fsc)
3883 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003884 if (pvolume_info->multiuser)
3885 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3886 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003887 if (pvolume_info->strict_io)
3888 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003889 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003890 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003891 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3892 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003893 if (pvolume_info->mfsymlinks) {
3894 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003895 /*
3896 * Our SFU ("Services for Unix" emulation does not allow
3897 * creating symlinks but does allow reading existing SFU
3898 * symlinks (it does allow both creating and reading SFU
3899 * style mknod and FIFOs though). When "mfsymlinks" and
3900 * "sfu" are both enabled at the same time, it allows
3901 * reading both types of symlinks, but will only create
3902 * them with mfsymlinks format. This allows better
3903 * Apple compatibility (probably better for Samba too)
3904 * while still recognizing old Windows style symlinks.
3905 */
3906 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003907 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003908 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003909 }
Steve French3b795212008-11-13 19:45:32 +00003910
3911 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003912 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003913
3914 if (pvolume_info->prepath) {
3915 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
3916 if (cifs_sb->prepath == NULL)
3917 return -ENOMEM;
3918 }
3919
3920 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003921}
3922
Paulo Alcantara56c762e2018-11-14 13:03:14 -02003923void
3924cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003925{
Sean Finneyb9468452011-04-11 13:19:32 +00003926 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003927 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003928 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003929 kfree(volume_info->domainname);
3930 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003931 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003932}
3933
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003934void
3935cifs_cleanup_volume_info(struct smb_vol *volume_info)
3936{
3937 if (!volume_info)
3938 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02003939 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003940 kfree(volume_info);
3941}
3942
Paulo Alcantara56c762e2018-11-14 13:03:14 -02003943/* Release all succeed connections */
3944static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
3945 unsigned int xid,
3946 struct TCP_Server_Info *server,
3947 struct cifs_ses *ses, struct cifs_tcon *tcon)
3948{
3949 int rc = 0;
3950
3951 if (tcon)
3952 cifs_put_tcon(tcon);
3953 else if (ses)
3954 cifs_put_smb_ses(ses);
3955 else if (server)
3956 cifs_put_tcp_session(server, 0);
3957 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
3958 free_xid(xid);
3959}
3960
3961/* Get connections for tcp, ses and tcon */
3962static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
3963 unsigned int *xid,
3964 struct TCP_Server_Info **nserver,
3965 struct cifs_ses **nses, struct cifs_tcon **ntcon)
3966{
3967 int rc = 0;
3968 struct TCP_Server_Info *server;
3969 struct cifs_ses *ses;
3970 struct cifs_tcon *tcon;
3971
3972 *nserver = NULL;
3973 *nses = NULL;
3974 *ntcon = NULL;
3975
3976 *xid = get_xid();
3977
3978 /* get a reference to a tcp session */
3979 server = cifs_get_tcp_session(vol);
3980 if (IS_ERR(server)) {
3981 rc = PTR_ERR(server);
3982 return rc;
3983 }
3984
3985 *nserver = server;
3986
3987 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
3988 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
3989 else
3990 server->max_credits = vol->max_credits;
3991
3992 /* get a reference to a SMB session */
3993 ses = cifs_get_smb_ses(server, vol);
3994 if (IS_ERR(ses)) {
3995 rc = PTR_ERR(ses);
3996 return rc;
3997 }
3998
3999 *nses = ses;
4000
4001 if ((vol->persistent == true) && (!(ses->server->capabilities &
4002 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
4003 cifs_dbg(VFS, "persistent handles not supported by server\n");
4004 return -EOPNOTSUPP;
4005 }
4006
4007 /* search for existing tcon to this server share */
4008 tcon = cifs_get_tcon(ses, vol);
4009 if (IS_ERR(tcon)) {
4010 rc = PTR_ERR(tcon);
4011 return rc;
4012 }
4013
4014 *ntcon = tcon;
4015
4016 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4017 if (tcon->posix_extensions)
4018 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4019
4020 /* tell server which Unix caps we support */
4021 if (cap_unix(tcon->ses)) {
4022 /*
4023 * reset of caps checks mount to see if unix extensions disabled
4024 * for just this mount.
4025 */
4026 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4027 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4028 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4029 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4030 return -EACCES;
4031 } else
4032 tcon->unix_ext = 0; /* server does not support them */
4033
4034 /* do not care if a following call succeed - informational */
4035 if (!tcon->pipe && server->ops->qfs_tcon)
4036 server->ops->qfs_tcon(*xid, tcon);
4037
4038 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4039 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4040
4041 return 0;
4042}
4043
4044static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4045 struct cifs_tcon *tcon)
4046{
4047 struct tcon_link *tlink;
4048
4049 /* hang the tcon off of the superblock */
4050 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4051 if (tlink == NULL)
4052 return -ENOMEM;
4053
4054 tlink->tl_uid = ses->linux_uid;
4055 tlink->tl_tcon = tcon;
4056 tlink->tl_time = jiffies;
4057 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4058 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4059
4060 cifs_sb->master_tlink = tlink;
4061 spin_lock(&cifs_sb->tlink_tree_lock);
4062 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4063 spin_unlock(&cifs_sb->tlink_tree_lock);
4064
4065 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4066 TLINK_IDLE_EXPIRE);
4067 return 0;
4068}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004069
Steve French2d6d5892009-04-09 00:36:44 +00004070#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004071/*
4072 * cifs_build_path_to_root returns full path to root when we do not have an
4073 * exiting connection (tcon)
4074 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004075static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004076build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004077 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004078{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004079 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004080 unsigned int pplen = useppath && vol->prepath ?
4081 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004082 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004083
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004084 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004085 if (full_path == NULL)
4086 return ERR_PTR(-ENOMEM);
4087
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004088 strncpy(full_path, vol->UNC, unc_len);
4089 pos = full_path + unc_len;
4090
4091 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004092 *pos = CIFS_DIR_SEP(cifs_sb);
4093 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004094 pos += pplen;
4095 }
4096
4097 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004098 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004099 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004100 return full_path;
4101}
Sean Finneydd613942011-04-11 13:19:30 +00004102
Paulo Alcantara1c780222018-11-14 16:24:03 -02004103/**
4104 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4105 *
Sean Finneydd613942011-04-11 13:19:30 +00004106 *
Sean Finney046462a2011-04-11 13:19:33 +00004107 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4108 * to a string containing updated options for the submount. Otherwise it
4109 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004110 *
4111 * Returns the rc from get_dfs_path to the caller, which can be used to
4112 * determine whether there were referrals.
4113 */
4114static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004115expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004116 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00004117 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00004118{
4119 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004120 struct dfs_info3_param referral = {0};
Sean Finneydd613942011-04-11 13:19:30 +00004121 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4122
Aurelien Aptel83930722018-09-20 18:10:25 -07004123 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4124 return -EREMOTE;
4125
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004126 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004127 if (IS_ERR(full_path))
4128 return PTR_ERR(full_path);
4129
4130 /* For DFS paths, skip the first '\' of the UNC */
4131 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4132
Paulo Alcantara1c780222018-11-14 16:24:03 -02004133 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4134 ref_path, &referral, NULL);
4135 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004136 char *fake_devname = NULL;
4137
4138 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004139 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004140 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004141 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004142
Sean Finneydd613942011-04-11 13:19:30 +00004143 if (IS_ERR(mdata)) {
4144 rc = PTR_ERR(mdata);
4145 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004146 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004147 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004148 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004149 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004150 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004151 kfree(fake_devname);
4152 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004153 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004154 }
4155 kfree(full_path);
4156 return rc;
4157}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004158
4159static inline int get_next_dfs_tgt(const char *path,
4160 struct dfs_cache_tgt_list *tgt_list,
4161 struct dfs_cache_tgt_iterator **tgt_it)
4162{
4163 if (!*tgt_it)
4164 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4165 else
4166 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4167 return !*tgt_it ? -EHOSTDOWN : 0;
4168}
4169
4170static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4171 struct smb_vol *fake_vol, struct smb_vol *vol)
4172{
4173 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4174 int len = strlen(tgt) + 2;
4175 char *new_unc;
4176
4177 new_unc = kmalloc(len, GFP_KERNEL);
4178 if (!new_unc)
4179 return -ENOMEM;
4180 snprintf(new_unc, len, "\\%s", tgt);
4181
4182 kfree(vol->UNC);
4183 vol->UNC = new_unc;
4184
4185 if (fake_vol->prepath) {
4186 kfree(vol->prepath);
4187 vol->prepath = fake_vol->prepath;
4188 fake_vol->prepath = NULL;
4189 }
4190 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4191
4192 return 0;
4193}
4194
4195static int setup_dfs_tgt_conn(const char *path,
4196 const struct dfs_cache_tgt_iterator *tgt_it,
4197 struct cifs_sb_info *cifs_sb,
4198 struct smb_vol *vol,
4199 unsigned int *xid,
4200 struct TCP_Server_Info **server,
4201 struct cifs_ses **ses,
4202 struct cifs_tcon **tcon)
4203{
4204 int rc;
4205 struct dfs_info3_param ref = {0};
4206 char *mdata = NULL, *fake_devname = NULL;
4207 struct smb_vol fake_vol = {0};
4208
4209 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4210
4211 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4212 if (rc)
4213 return rc;
4214
4215 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4216 &fake_devname);
4217 free_dfs_info_param(&ref);
4218
4219 if (IS_ERR(mdata)) {
4220 rc = PTR_ERR(mdata);
4221 mdata = NULL;
4222 } else {
4223 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4224 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4225 false);
4226 }
4227 kfree(mdata);
4228 kfree(fake_devname);
4229
4230 if (!rc) {
4231 /*
4232 * We use a 'fake_vol' here because we need pass it down to the
4233 * mount_{get,put} functions to test connection against new DFS
4234 * targets.
4235 */
4236 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4237 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4238 tcon);
4239 if (!rc) {
4240 /*
4241 * We were able to connect to new target server.
4242 * Update current volume info with new target server.
4243 */
4244 rc = update_vol_info(tgt_it, &fake_vol, vol);
4245 }
4246 }
4247 cifs_cleanup_volume_info_contents(&fake_vol);
4248 return rc;
4249}
4250
4251static int mount_do_dfs_failover(const char *path,
4252 struct cifs_sb_info *cifs_sb,
4253 struct smb_vol *vol,
4254 struct cifs_ses *root_ses,
4255 unsigned int *xid,
4256 struct TCP_Server_Info **server,
4257 struct cifs_ses **ses,
4258 struct cifs_tcon **tcon)
4259{
4260 int rc;
4261 struct dfs_cache_tgt_list tgt_list;
4262 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4263
4264 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4265 return -EOPNOTSUPP;
4266
4267 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4268 if (rc)
4269 return rc;
4270
4271 for (;;) {
4272 /* Get next DFS target server - if any */
4273 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4274 if (rc)
4275 break;
4276 /* Connect to next DFS target */
4277 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4278 ses, tcon);
4279 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4280 break;
4281 }
4282 if (!rc) {
4283 /*
4284 * Update DFS target hint in DFS referral cache with the target
4285 * server we successfully reconnected to.
4286 */
4287 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4288 cifs_sb->local_nls,
4289 cifs_remap(cifs_sb), path,
4290 tgt_it);
4291 }
4292 dfs_cache_free_tgts(&tgt_list);
4293 return rc;
4294}
Steve French2d6d5892009-04-09 00:36:44 +00004295#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004296
Jeff Layton04db79b2011-07-06 08:10:38 -04004297static int
4298cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004299 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004301 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004302
Steve Frenchc7c137b2018-06-06 17:59:29 -05004303 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004304 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Jeff Layton7586b762008-12-01 18:41:49 -05004306 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004307 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004308 kfree(volume_info->username);
4309 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004310 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004312 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004314 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004315 /* In userspace mount helper we can get user name from alternate
4316 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004317 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318 }
4319
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004321 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004322 /* load_nls_default cannot return null */
4323 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004325 volume_info->local_nls = load_nls(volume_info->iocharset);
4326 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004327 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004328 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004329 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 }
4331 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004332
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004333 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004334}
4335
4336struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004337cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004338{
4339 int rc;
4340 struct smb_vol *volume_info;
4341
Jeff Layton6ee95422012-11-26 11:09:57 -05004342 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004343 if (!volume_info)
4344 return ERR_PTR(-ENOMEM);
4345
Steve Frenchc7c137b2018-06-06 17:59:29 -05004346 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004347 if (rc) {
4348 cifs_cleanup_volume_info(volume_info);
4349 volume_info = ERR_PTR(rc);
4350 }
4351
4352 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004353}
4354
Aurelien Aptela6b50582016-05-25 19:59:09 +02004355static int
4356cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4357 unsigned int xid,
4358 struct cifs_tcon *tcon,
4359 struct cifs_sb_info *cifs_sb,
4360 char *full_path)
4361{
4362 int rc;
4363 char *s;
4364 char sep, tmp;
4365
4366 sep = CIFS_DIR_SEP(cifs_sb);
4367 s = full_path;
4368
4369 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4370 while (rc == 0) {
4371 /* skip separators */
4372 while (*s == sep)
4373 s++;
4374 if (!*s)
4375 break;
4376 /* next separator */
4377 while (*s && *s != sep)
4378 s++;
4379
4380 /*
4381 * temporarily null-terminate the path at the end of
4382 * the current component
4383 */
4384 tmp = *s;
4385 *s = 0;
4386 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4387 full_path);
4388 *s = tmp;
4389 }
4390 return rc;
4391}
4392
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004393/*
4394 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4395 * otherwise 0.
4396 */
4397static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4398 const unsigned int xid,
4399 struct TCP_Server_Info *server,
4400 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004401{
Jeff Layton1daaae82012-03-21 06:30:40 -04004402 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004403 char *full_path;
4404
4405 if (!server->ops->is_path_accessible)
4406 return -EOPNOTSUPP;
4407
4408 /*
4409 * cifs_build_path_to_root works only when we have a valid tcon
4410 */
4411 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4412 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4413 if (full_path == NULL)
4414 return -ENOMEM;
4415
4416 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4417
4418 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4419 full_path);
4420 if (rc != 0 && rc != -EREMOTE) {
4421 kfree(full_path);
4422 return rc;
4423 }
4424
4425 if (rc != -EREMOTE) {
4426 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
4427 cifs_sb,
4428 full_path);
4429 if (rc != 0) {
4430 cifs_dbg(VFS, "cannot query dirs between root and final path, "
4431 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4432 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4433 rc = 0;
4434 }
4435 }
4436
4437 kfree(full_path);
4438 return rc;
4439}
4440
4441#ifdef CONFIG_CIFS_DFS_UPCALL
4442int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4443{
4444 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004445 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004446 struct cifs_ses *ses;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004447 struct cifs_tcon *root_tcon = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004448 struct cifs_tcon *tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004449 struct TCP_Server_Info *server;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004450 char *root_path = NULL, *full_path = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004451 char *old_mountdata;
4452 int count;
Al Virodd854462011-06-17 08:24:42 -04004453
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004454 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4455 if (!rc && tcon) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004456 /* If not a standalone DFS root, then check if path is remote */
4457 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4458 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4459 NULL);
4460 if (rc) {
4461 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4462 if (!rc)
4463 goto out;
4464 if (rc != -EREMOTE)
4465 goto error;
4466 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004467 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004468 /*
4469 * If first DFS target server went offline and we failed to connect it,
4470 * server and ses pointers are NULL at this point, though we still have
4471 * chance to get a cached DFS referral in expand_dfs_referral() and
4472 * retry next target available in it.
4473 *
4474 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4475 * performed against DFS path and *no* requests will be sent to server
4476 * for any new DFS referrals. Hence it's safe to skip checking whether
4477 * server or ses ptr is NULL.
4478 */
4479 if (rc == -EACCES || rc == -EOPNOTSUPP)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004480 goto error;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004481
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004482 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4483 if (IS_ERR(root_path)) {
4484 rc = PTR_ERR(root_path);
4485 root_path = NULL;
4486 goto error;
4487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004489 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4490 if (IS_ERR(full_path)) {
4491 rc = PTR_ERR(full_path);
4492 full_path = NULL;
4493 goto error;
4494 }
Sean Finneyc1508ca2011-04-11 13:19:31 +00004495 /*
4496 * Perform an unconditional check for whether there are DFS
4497 * referrals for this path without prefix, to provide support
4498 * for DFS referrals from w2k8 servers which don't seem to respond
4499 * with PATH_NOT_COVERED to requests that include the prefix.
4500 * Chase the referral if found, otherwise continue normally.
4501 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004502 old_mountdata = cifs_sb->mountdata;
4503 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004504
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004505 if (cifs_sb->mountdata == NULL) {
4506 rc = -ENOENT;
4507 goto error;
4508 }
4509
4510 if (cifs_sb->mountdata != old_mountdata) {
4511 /* If we were redirected, reconnect to new target server */
4512 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4513 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4514 }
4515 if (rc) {
4516 if (rc == -EACCES || rc == -EOPNOTSUPP)
4517 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004518 /* Perform DFS failover to any other DFS targets */
4519 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4520 &xid, &server, &ses, &tcon);
4521 if (rc)
4522 goto error;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004523 }
4524
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004525 kfree(root_path);
4526 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4527 if (IS_ERR(root_path)) {
4528 rc = PTR_ERR(root_path);
4529 root_path = NULL;
4530 goto error;
4531 }
4532 /* Cache out resolved root server */
4533 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4534 root_path + 1, NULL, NULL);
4535 /*
4536 * Save root tcon for additional DFS requests to update or create a new
4537 * DFS cache entry, or even perform DFS failover.
4538 */
4539 spin_lock(&cifs_tcp_ses_lock);
4540 tcon->tc_count++;
4541 tcon->dfs_path = root_path;
4542 root_path = NULL;
4543 tcon->remap = cifs_remap(cifs_sb);
4544 spin_unlock(&cifs_tcp_ses_lock);
4545
4546 root_tcon = tcon;
4547
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004548 for (count = 1; ;) {
4549 if (!rc && tcon) {
4550 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4551 if (!rc || rc != -EREMOTE)
4552 break;
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004553 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004554 /*
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004555 * BB: when we implement proper loop detection,
4556 * we will remove this check. But now we need it
4557 * to prevent an indefinite loop if 'DFS tree' is
4558 * misconfigured (i.e. has loops).
Steve French6d3ea7e2012-11-28 22:34:41 -06004559 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004560 if (count++ > MAX_NESTED_LINKS) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004561 rc = -ELOOP;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004562 break;
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004563 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004564
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004565 kfree(full_path);
4566 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4567 if (IS_ERR(full_path)) {
4568 rc = PTR_ERR(full_path);
4569 full_path = NULL;
4570 break;
4571 }
4572
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004573 old_mountdata = cifs_sb->mountdata;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004574 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004575 true);
4576 if (rc)
4577 break;
Jeff Layton7b91e262009-07-23 15:22:30 -04004578
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004579 if (cifs_sb->mountdata != old_mountdata) {
4580 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4581 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4582 &tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004583 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004584 if (rc) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004585 if (rc == -EACCES || rc == -EOPNOTSUPP)
4586 break;
4587 /* Perform DFS failover to any other DFS targets */
4588 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4589 root_tcon->ses, &xid,
4590 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004591 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4592 !ses)
4593 goto error;
4594 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004595 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004596 cifs_put_tcon(root_tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004597
Jeff Layton9d002df2010-10-06 19:51:11 -04004598 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004599 goto error;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004600
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004601 spin_lock(&cifs_tcp_ses_lock);
4602 if (!tcon->dfs_path) {
4603 /* Save full path in new tcon to do failover when reconnecting tcons */
4604 tcon->dfs_path = full_path;
4605 full_path = NULL;
4606 tcon->remap = cifs_remap(cifs_sb);
4607 }
4608 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
YueHaibing2f0a6172018-12-18 01:34:39 +00004609 strlen(tcon->dfs_path),
4610 GFP_ATOMIC);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004611 if (!cifs_sb->origin_fullpath) {
4612 spin_unlock(&cifs_tcp_ses_lock);
4613 rc = -ENOMEM;
4614 goto error;
4615 }
4616 spin_unlock(&cifs_tcp_ses_lock);
4617
Paulo Alcantarae511d312018-11-14 17:16:44 -02004618 rc = dfs_cache_add_vol(vol, cifs_sb->origin_fullpath);
4619 if (rc) {
4620 kfree(cifs_sb->origin_fullpath);
4621 goto error;
4622 }
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004623 /*
4624 * After reconnecting to a different server, unique ids won't
4625 * match anymore, so we disable serverino. This prevents
4626 * dentry revalidation to think the dentry are stale (ESTALE).
4627 */
4628 cifs_autodisable_serverino(cifs_sb);
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004629out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004630 free_xid(xid);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004631 return mount_setup_tlink(cifs_sb, ses, tcon);
4632
4633error:
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004634 kfree(full_path);
4635 kfree(root_path);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004636 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637 return rc;
4638}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004639#else
4640int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4641{
4642 int rc = 0;
4643 unsigned int xid;
4644 struct cifs_ses *ses;
4645 struct cifs_tcon *tcon;
4646 struct TCP_Server_Info *server;
4647
4648 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4649 if (rc)
4650 goto error;
4651
4652 if (tcon) {
4653 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4654 if (rc == -EREMOTE)
4655 rc = -EOPNOTSUPP;
4656 if (rc)
4657 goto error;
4658 }
4659
4660 free_xid(xid);
4661
4662 return mount_setup_tlink(cifs_sb, ses, tcon);
4663
4664error:
4665 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4666 return rc;
4667}
4668#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669
Jeff Layton8d1bca32011-06-11 21:17:10 -04004670/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01004671 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04004672 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04004674CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00004675 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676 const struct nls_table *nls_codepage)
4677{
4678 struct smb_hdr *smb_buffer;
4679 struct smb_hdr *smb_buffer_response;
4680 TCONX_REQ *pSMB;
4681 TCONX_RSP *pSMBr;
4682 unsigned char *bcc_ptr;
4683 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05004684 int length;
4685 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004686
4687 if (ses == NULL)
4688 return -EIO;
4689
4690 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00004691 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004692 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00004693
Linus Torvalds1da177e2005-04-16 15:20:36 -07004694 smb_buffer_response = smb_buffer;
4695
4696 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
4697 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07004698
Pavel Shilovsky88257362012-05-23 14:01:59 +04004699 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700 smb_buffer->Uid = ses->Suid;
4701 pSMB = (TCONX_REQ *) smb_buffer;
4702 pSMBr = (TCONX_RSP *) smb_buffer_response;
4703
4704 pSMB->AndXCommand = 0xFF;
4705 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004706 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01004707 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08004708 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00004709 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08004710 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00004711 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08004712 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004713 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08004714 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
4715 specified as required (when that support is added to
4716 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00004717 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08004718 by Samba (not sure whether other servers allow
4719 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00004720#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04004721 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05004722 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05004723 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00004724 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05004725 SECMODE_PW_ENCRYPT ? true : false,
4726 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00004727 else
4728#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06004729 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05004730 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05004731 if (rc) {
4732 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
4733 __func__, rc);
4734 cifs_buf_release(smb_buffer);
4735 return rc;
4736 }
Steve Frencheeac8042006-01-13 21:34:58 -08004737
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004738 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004739 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00004740 /* must align unicode strings */
4741 *bcc_ptr = 0; /* null byte password */
4742 bcc_ptr++;
4743 }
Steve Frencheeac8042006-01-13 21:34:58 -08004744 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004745
Jeff Layton38d77c52013-05-26 07:01:00 -04004746 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4748
4749 if (ses->capabilities & CAP_STATUS32) {
4750 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
4751 }
4752 if (ses->capabilities & CAP_DFS) {
4753 smb_buffer->Flags2 |= SMBFLG2_DFS;
4754 }
4755 if (ses->capabilities & CAP_UNICODE) {
4756 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
4757 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06004758 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004759 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004760 (/* server len*/ + 256 /* share len */), nls_codepage);
4761 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762 bcc_ptr += 2; /* skip trailing null */
4763 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764 strcpy(bcc_ptr, tree);
4765 bcc_ptr += strlen(tree) + 1;
4766 }
4767 strcpy(bcc_ptr, "?????");
4768 bcc_ptr += strlen("?????");
4769 bcc_ptr += 1;
4770 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004771 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4772 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004773 pSMB->ByteCount = cpu_to_le16(count);
4774
Steve French133672e2007-11-13 22:41:37 +00004775 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004776 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01004779 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004780 bool is_unicode;
4781
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004783 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004784 tcon->tid = smb_buffer_response->Tid;
4785 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004786 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004787 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004788 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4789 is_unicode = true;
4790 else
4791 is_unicode = false;
4792
Jeff Laytoncc20c032009-04-30 07:16:21 -04004793
Steve French50c2f752007-07-13 00:33:32 +00004794 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004795 if (length == 3) {
4796 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4797 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004798 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01004799 tcon->ipc = true;
4800 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00004801 }
4802 } else if (length == 2) {
4803 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4804 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05004805 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004806 }
4807 }
Steve French50c2f752007-07-13 00:33:32 +00004808 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004809 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05004810 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04004811
4812 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004813 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004814 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004815 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004816 nls_codepage);
4817
Joe Perchesf96637b2013-05-04 22:12:25 -05004818 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004819
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004820 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004821 (smb_buffer_response->WordCount == 7))
4822 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004823 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4824 else
4825 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05004826 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004827 }
4828
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004829 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004830 return rc;
4831}
4832
Al Viro2e32cf52013-10-03 12:53:37 -04004833static void delayed_free(struct rcu_head *p)
4834{
4835 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
4836 unload_nls(sbi->local_nls);
4837 kfree(sbi);
4838}
4839
Al Viro2a9b9952011-06-17 09:27:16 -04004840void
4841cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004842{
Jeff Laytonb647c352010-10-28 11:16:44 -04004843 struct rb_root *root = &cifs_sb->tlink_tree;
4844 struct rb_node *node;
4845 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004846
Jeff Layton2de970f2010-10-06 19:51:12 -04004847 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4848
Jeff Laytonb647c352010-10-28 11:16:44 -04004849 spin_lock(&cifs_sb->tlink_tree_lock);
4850 while ((node = rb_first(root))) {
4851 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4852 cifs_get_tlink(tlink);
4853 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4854 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004855
Jeff Laytonb647c352010-10-28 11:16:44 -04004856 spin_unlock(&cifs_sb->tlink_tree_lock);
4857 cifs_put_tlink(tlink);
4858 spin_lock(&cifs_sb->tlink_tree_lock);
4859 }
4860 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004861
Al Virod757d712011-06-17 09:42:43 -04004862 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02004863 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004864#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02004865 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004866 kfree(cifs_sb->origin_fullpath);
4867#endif
Al Viro2e32cf52013-10-03 12:53:37 -04004868 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00004869}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004871int
4872cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004873{
4874 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004875 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004876
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004877 if (!server->ops->need_neg || !server->ops->negotiate)
4878 return -ENOSYS;
4879
Jeff Layton198b5682010-04-24 07:57:48 -04004880 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004881 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04004882 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004883
Pavel Shilovsky45275782012-05-17 17:53:29 +04004884 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004885
4886 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04004887 if (rc == 0) {
4888 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004889 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004890 server->tcpStatus = CifsGood;
4891 else
4892 rc = -EHOSTDOWN;
4893 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894 }
Steve French26b994f2008-08-06 05:11:33 +00004895
Jeff Layton198b5682010-04-24 07:57:48 -04004896 return rc;
4897}
Steve French26b994f2008-08-06 05:11:33 +00004898
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004899int
4900cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
4901 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04004902{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004903 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04004904 struct TCP_Server_Info *server = ses->server;
4905
Jeff Layton198b5682010-04-24 07:57:48 -04004906 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004907 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004908 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00004909
Joe Perchesf96637b2013-05-04 22:12:25 -05004910 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00004911 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004912
Shu Wangf5c4ba82017-09-08 18:48:33 +08004913 if (ses->auth_key.response) {
Steve French2a182872018-03-29 12:16:34 -05004914 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
Shu Wangf5c4ba82017-09-08 18:48:33 +08004915 ses->auth_key.response);
4916 kfree(ses->auth_key.response);
4917 ses->auth_key.response = NULL;
4918 ses->auth_key.len = 0;
4919 }
4920
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004921 if (server->ops->sess_setup)
4922 rc = server->ops->sess_setup(xid, ses, nls_info);
4923
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05004924 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05004925 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004926
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927 return rc;
4928}
4929
Jeff Layton8a8798a2012-01-17 16:09:15 -05004930static int
4931cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4932{
Jeff Layton3f618222013-06-12 19:52:14 -05004933 vol->sectype = ses->sectype;
4934
4935 /* krb5 is special, since we don't need username or pw */
4936 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05004937 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05004938
4939 return cifs_set_cifscreds(vol, ses);
4940}
4941
Steve French96daf2b2011-05-27 04:34:02 +00004942static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004943cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04004944{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004945 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004946 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4947 struct cifs_ses *ses;
4948 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004949 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004950
4951 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004952 if (vol_info == NULL)
4953 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004954
Jeff Layton9d002df2010-10-06 19:51:11 -04004955 vol_info->local_nls = cifs_sb->local_nls;
4956 vol_info->linux_uid = fsuid;
4957 vol_info->cred_uid = fsuid;
4958 vol_info->UNC = master_tcon->treeName;
4959 vol_info->retry = master_tcon->retry;
4960 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05004961 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04004962 vol_info->local_lease = master_tcon->local_lease;
4963 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004964 vol_info->sectype = master_tcon->ses->sectype;
4965 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004966
Jeff Layton8a8798a2012-01-17 16:09:15 -05004967 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4968 if (rc) {
4969 tcon = ERR_PTR(rc);
4970 goto out;
4971 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004972
4973 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304974 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004975 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304976 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004977
4978 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4979 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004980 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004981 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04004982 goto out;
4983 }
4984
4985 tcon = cifs_get_tcon(ses, vol_info);
4986 if (IS_ERR(tcon)) {
4987 cifs_put_smb_ses(ses);
4988 goto out;
4989 }
4990
Steve Frenchce558b02018-05-31 19:16:54 -05004991 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4992 if (tcon->posix_extensions)
4993 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05004994
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004995 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004996 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05004997
Jeff Layton9d002df2010-10-06 19:51:11 -04004998out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004999 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01005000 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005001 kfree(vol_info);
5002
5003 return tcon;
5004}
5005
Steve French96daf2b2011-05-27 04:34:02 +00005006struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005007cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5008{
5009 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5010}
5011
Jeff Laytonb647c352010-10-28 11:16:44 -04005012/* find and return a tlink with given uid */
5013static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005014tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005015{
5016 struct rb_node *node = root->rb_node;
5017 struct tcon_link *tlink;
5018
5019 while (node) {
5020 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5021
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005022 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005023 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005024 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005025 node = node->rb_right;
5026 else
5027 return tlink;
5028 }
5029 return NULL;
5030}
5031
5032/* insert a tcon_link into the tree */
5033static void
5034tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5035{
5036 struct rb_node **new = &(root->rb_node), *parent = NULL;
5037 struct tcon_link *tlink;
5038
5039 while (*new) {
5040 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5041 parent = *new;
5042
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005043 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005044 new = &((*new)->rb_left);
5045 else
5046 new = &((*new)->rb_right);
5047 }
5048
5049 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5050 rb_insert_color(&new_tlink->tl_rbnode, root);
5051}
5052
Jeff Layton9d002df2010-10-06 19:51:11 -04005053/*
5054 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5055 * current task.
5056 *
5057 * If the superblock doesn't refer to a multiuser mount, then just return
5058 * the master tcon for the mount.
5059 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305060 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005061 * exists, then check to see if it's pending construction. If it is then wait
5062 * for construction to complete. Once it's no longer pending, check to see if
5063 * it failed and either return an error or retry construction, depending on
5064 * the timeout.
5065 *
5066 * If one doesn't exist then insert a new tcon_link struct into the tree and
5067 * try to construct a new one.
5068 */
5069struct tcon_link *
5070cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5071{
5072 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005073 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005074 struct tcon_link *tlink, *newtlink;
5075
5076 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5077 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5078
5079 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005080 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005081 if (tlink)
5082 cifs_get_tlink(tlink);
5083 spin_unlock(&cifs_sb->tlink_tree_lock);
5084
5085 if (tlink == NULL) {
5086 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5087 if (newtlink == NULL)
5088 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005089 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005090 newtlink->tl_tcon = ERR_PTR(-EACCES);
5091 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5092 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5093 cifs_get_tlink(newtlink);
5094
Jeff Layton9d002df2010-10-06 19:51:11 -04005095 spin_lock(&cifs_sb->tlink_tree_lock);
5096 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005097 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005098 if (tlink) {
5099 cifs_get_tlink(tlink);
5100 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005101 kfree(newtlink);
5102 goto wait_for_construction;
5103 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005104 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005105 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5106 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005107 } else {
5108wait_for_construction:
5109 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005110 TASK_INTERRUPTIBLE);
5111 if (ret) {
5112 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005113 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005114 }
5115
5116 /* if it's good, return it */
5117 if (!IS_ERR(tlink->tl_tcon))
5118 return tlink;
5119
5120 /* return error if we tried this already recently */
5121 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5122 cifs_put_tlink(tlink);
5123 return ERR_PTR(-EACCES);
5124 }
5125
5126 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5127 goto wait_for_construction;
5128 }
5129
5130 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5131 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5132 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5133
5134 if (IS_ERR(tlink->tl_tcon)) {
5135 cifs_put_tlink(tlink);
5136 return ERR_PTR(-EACCES);
5137 }
5138
5139 return tlink;
5140}
Jeff Layton2de970f2010-10-06 19:51:12 -04005141
5142/*
5143 * periodic workqueue job that scans tcon_tree for a superblock and closes
5144 * out tcons.
5145 */
5146static void
5147cifs_prune_tlinks(struct work_struct *work)
5148{
5149 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5150 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005151 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005152 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005153 struct rb_node *tmp;
5154 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005155
Jeff Laytonb647c352010-10-28 11:16:44 -04005156 /*
5157 * Because we drop the spinlock in the loop in order to put the tlink
5158 * it's not guarded against removal of links from the tree. The only
5159 * places that remove entries from the tree are this function and
5160 * umounts. Because this function is non-reentrant and is canceled
5161 * before umount can proceed, this is safe.
5162 */
5163 spin_lock(&cifs_sb->tlink_tree_lock);
5164 node = rb_first(root);
5165 while (node != NULL) {
5166 tmp = node;
5167 node = rb_next(tmp);
5168 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5169
5170 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5171 atomic_read(&tlink->tl_count) != 0 ||
5172 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5173 continue;
5174
5175 cifs_get_tlink(tlink);
5176 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5177 rb_erase(tmp, root);
5178
Jeff Layton2de970f2010-10-06 19:51:12 -04005179 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005180 cifs_put_tlink(tlink);
5181 spin_lock(&cifs_sb->tlink_tree_lock);
5182 }
5183 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005184
Jeff Laytonda472fc2012-03-23 14:40:53 -04005185 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005186 TLINK_IDLE_EXPIRE);
5187}