blob: f66529679ca2c6238c02c8c38b0e202c3b27398c [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);
436 if (!server->hostname) {
437 cifs_dbg(FYI, "%s: failed to extract hostname from target: %d\n",
438 __func__, -ENOMEM);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200439 }
440}
441
442static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
443 struct dfs_cache_tgt_list *tl,
444 struct dfs_cache_tgt_iterator **it)
445{
446 if (!cifs_sb->origin_fullpath)
447 return -EOPNOTSUPP;
448 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
449}
450#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Jeff Laytond5c56052008-12-01 18:42:33 -0500452/*
453 * cifs tcp session reconnection
454 *
455 * mark tcp session as reconnecting so temporarily locked
456 * mark all smb sessions as reconnecting for tcp session
457 * reconnect tcp session
458 * wake up waiters on reconnection? - (not needed currently)
459 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400460int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461cifs_reconnect(struct TCP_Server_Info *server)
462{
463 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500464 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000465 struct cifs_ses *ses;
466 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000467 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400468 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200469#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara23324402018-11-20 14:37:18 -0200470 struct cifs_sb_info *cifs_sb = NULL;
471 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200472 struct dfs_cache_tgt_iterator *tgt_it = NULL;
473#endif
Steve French50c2f752007-07-13 00:33:32 +0000474
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200476 server->nr_targets = 1;
477#ifdef CONFIG_CIFS_DFS_UPCALL
478 cifs_sb = find_super_by_tcp(server);
479 if (IS_ERR(cifs_sb)) {
480 rc = PTR_ERR(cifs_sb);
481 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
482 __func__, rc);
483 cifs_sb = NULL;
484 } else {
485 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
Steve French55a7f002019-01-01 17:19:45 -0600486 if (rc && (rc != -EOPNOTSUPP)) {
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200487 cifs_dbg(VFS, "%s: no target servers for DFS failover\n",
488 __func__);
489 } else {
490 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
491 }
492 }
493 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
494 server->nr_targets);
495#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000496 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000497 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 next time through the loop */
499 spin_unlock(&GlobalMid_Lock);
500 return rc;
501 } else
502 server->tcpStatus = CifsNeedReconnect;
503 spin_unlock(&GlobalMid_Lock);
504 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400505 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Steve French6e4d3bb2018-09-22 11:25:04 -0500507 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500508 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
510 /* before reconnecting the tcp session, mark the smb session (uid)
511 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500512 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
513 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530514 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500515 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000516 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500517 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500518 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000519 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500520 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100522 if (ses->tcon_ipc)
523 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530525 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500528 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500529 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000530 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500531 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
532 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800533 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500534 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
535 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 sock_release(server->ssocket);
537 server->ssocket = NULL;
538 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500539 server->sequence_number = 0;
540 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500541 kfree(server->session_key.response);
542 server->session_key.response = NULL;
543 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000544 server->lstrp = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500546 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400547 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500548 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500550 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
551 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400552 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
553 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400554 list_move(&mid_entry->qhead, &retry_list);
555 }
556 spin_unlock(&GlobalMid_Lock);
Rabin Vincent820962d2015-12-23 07:32:41 +0100557 mutex_unlock(&server->srv_mutex);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400558
Joe Perchesf96637b2013-05-04 22:12:25 -0500559 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400560 list_for_each_safe(tmp, tmp2, &retry_list) {
561 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500562 list_del_init(&mid_entry->qhead);
563 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400566 do {
Steve French6c3d8902006-07-31 22:46:20 +0000567 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300568
Jeff Layton73e216a2013-09-05 08:38:10 -0400569 mutex_lock(&server->srv_mutex);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200570 /*
571 * Set up next DFS target server (if any) for reconnect. If DFS
572 * feature is disabled, then we will retry last server we
573 * connected to before.
574 */
Long Li781a8052017-11-22 17:38:36 -0700575 if (cifs_rdma_enabled(server))
576 rc = smbd_reconnect(server);
577 else
578 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000579 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500580 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200581#ifdef CONFIG_CIFS_DFS_UPCALL
582 reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
583 &tgt_it);
584#endif
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200585 rc = reconn_set_ipaddr(server);
586 if (rc) {
587 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
588 __func__, rc);
589 }
Federico Sauter4afe2602015-03-17 17:45:28 +0100590 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700591 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 } else {
593 atomic_inc(&tcpSesReconnectCount);
594 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000595 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000596 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000597 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100598 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400600 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500601
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200602#ifdef CONFIG_CIFS_DFS_UPCALL
603 if (tgt_it) {
604 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
605 tgt_it);
606 if (rc) {
607 cifs_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
608 __func__, rc);
609 }
610 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
611 if (rc) {
612 cifs_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
613 __func__, rc);
614 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200615 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200616 }
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200617#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400618 if (server->tcpStatus == CifsNeedNegotiate)
619 mod_delayed_work(cifsiod_wq, &server->echo, 0);
620
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 return rc;
622}
623
Jeff Laytonc74093b2011-01-11 07:24:23 -0500624static void
625cifs_echo_request(struct work_struct *work)
626{
627 int rc;
628 struct TCP_Server_Info *server = container_of(work,
629 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400630 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500631
Jeff Layton247ec9b2011-02-04 17:09:50 -0500632 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400633 * If we need to renegotiate, set echo interval to zero to
634 * immediately call echo service where we can renegotiate.
635 */
636 if (server->tcpStatus == CifsNeedNegotiate)
637 echo_interval = 0;
638 else
639 echo_interval = server->echo_interval;
640
641 /*
642 * We cannot send an echo if it is disabled.
643 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500644 */
Steve French4fcd1812016-06-22 20:12:05 -0500645
646 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400647 server->tcpStatus == CifsExiting ||
648 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400649 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600650 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500651 goto requeue_echo;
652
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400653 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500654 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500655 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
656 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500657
658requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400659 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500660}
661
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400662static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400663allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400664{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400665 if (!server->bigbuf) {
666 server->bigbuf = (char *)cifs_buf_get();
667 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500668 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400669 msleep(3000);
670 /* retry will check if exiting */
671 return false;
672 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400673 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400674 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400675 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400676 }
677
Jeff Layton2a37ef92011-10-19 15:29:23 -0400678 if (!server->smallbuf) {
679 server->smallbuf = (char *)cifs_small_buf_get();
680 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500681 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400682 msleep(1000);
683 /* retry will check if exiting */
684 return false;
685 }
686 /* beginning of smb buffer is cleared in our buf_get */
687 } else {
688 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400689 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400690 }
691
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400692 return true;
693}
694
Jeff Laytonba749e62011-10-11 06:41:32 -0400695static bool
696server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400697{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300698 /*
699 * We need to wait 2 echo intervals to make sure we handle such
700 * situations right:
701 * 1s client sends a normal SMB request
702 * 2s client gets a response
703 * 30s echo workqueue job pops, and decides we got a response recently
704 * and don't need to send another
705 * ...
706 * 65s kernel_recvmsg times out, and we see that we haven't gotten
707 * a response in >60s.
708 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200709 if ((server->tcpStatus == CifsGood ||
710 server->tcpStatus == CifsNeedNegotiate) &&
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600711 time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
712 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
713 server->hostname, (2 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400714 cifs_reconnect(server);
715 wake_up(&server->response_q);
716 return true;
717 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400718
Jeff Laytonba749e62011-10-11 06:41:32 -0400719 return false;
720}
721
Al Viro71335662016-01-09 19:54:50 -0500722static int
723cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400724{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400725 int length = 0;
726 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400727
Al Viro71335662016-01-09 19:54:50 -0500728 smb_msg->msg_control = NULL;
729 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400730
Al Viro71335662016-01-09 19:54:50 -0500731 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500732 try_to_freeze();
733
Al Viro71335662016-01-09 19:54:50 -0500734 if (server_unresponsive(server))
735 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700736 if (cifs_rdma_enabled(server) && server->smbd_conn)
737 length = smbd_recv(server->smbd_conn, smb_msg);
738 else
739 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500740
741 if (server->tcpStatus == CifsExiting)
742 return -ESHUTDOWN;
743
744 if (server->tcpStatus == CifsNeedReconnect) {
745 cifs_reconnect(server);
746 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400747 }
748
Al Viro71335662016-01-09 19:54:50 -0500749 if (length == -ERESTARTSYS ||
750 length == -EAGAIN ||
751 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400752 /*
753 * Minimum sleep to prevent looping, allowing socket
754 * to clear and app threads to set tcpStatus
755 * CifsNeedReconnect if server hung.
756 */
757 usleep_range(1000, 2000);
758 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400759 continue;
Al Viro71335662016-01-09 19:54:50 -0500760 }
761
762 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500763 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400764 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500765 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400766 }
767 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400768 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400769}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400770
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400771int
772cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
773 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400774{
Al Viro71335662016-01-09 19:54:50 -0500775 struct msghdr smb_msg;
776 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100777 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400778
Al Viro71335662016-01-09 19:54:50 -0500779 return cifs_readv_from_socket(server, &smb_msg);
780}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400781
Al Viro71335662016-01-09 19:54:50 -0500782int
783cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700784 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500785{
786 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700787 struct bio_vec bv = {
788 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100789 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500790 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400791}
792
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400793static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400794is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400795{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400796 /*
797 * The first byte big endian of the length field,
798 * is actually not part of the length but the type
799 * with the most common, zero, as regular data.
800 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400801 switch (type) {
802 case RFC1002_SESSION_MESSAGE:
803 /* Regular SMB response */
804 return true;
805 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500806 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400807 break;
808 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500809 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400810 break;
811 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400812 /*
813 * We get this from Windows 98 instead of an error on
814 * SMB negprot response.
815 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500816 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400817 /* give server a second to clean up */
818 msleep(1000);
819 /*
820 * Always try 445 first on reconnect since we get NACK
821 * on some if we ever connected to port 139 (the NACK
822 * is since we do not begin with RFC1001 session
823 * initialize frame).
824 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400825 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400826 cifs_reconnect(server);
827 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400828 break;
829 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500830 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400831 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400832 }
833
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400834 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400835}
836
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400837void
838dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400839{
840#ifdef CONFIG_CIFS_STATS2
841 mid->when_received = jiffies;
842#endif
843 spin_lock(&GlobalMid_Lock);
844 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400845 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400846 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400847 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000848 /*
849 * Trying to handle/dequeue a mid after the send_recv()
850 * function has finished processing it is a bug.
851 */
852 if (mid->mid_flags & MID_DELETED)
853 printk_once(KERN_WARNING
854 "trying to dequeue a deleted mid\n");
855 else
856 list_del_init(&mid->qhead);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400857 spin_unlock(&GlobalMid_Lock);
858}
859
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400860static void
861handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400862 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400863{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400864 if (server->ops->check_trans2 &&
865 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400866 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400867 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400868 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400869 /* Was previous buf put in mpx struct for multi-rsp? */
870 if (!mid->multiRsp) {
871 /* smb buffer will be freed by user thread */
872 if (server->large_buf)
873 server->bigbuf = NULL;
874 else
875 server->smallbuf = NULL;
876 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400877 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400878}
879
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400880static void clean_demultiplex_info(struct TCP_Server_Info *server)
881{
882 int length;
883
884 /* take it off the list, if it's not already */
885 spin_lock(&cifs_tcp_ses_lock);
886 list_del_init(&server->tcp_ses_list);
887 spin_unlock(&cifs_tcp_ses_lock);
888
889 spin_lock(&GlobalMid_Lock);
890 server->tcpStatus = CifsExiting;
891 spin_unlock(&GlobalMid_Lock);
892 wake_up_all(&server->response_q);
893
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400894 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300895 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400896 if (server->credits <= 0)
897 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300898 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400899 /*
900 * Although there should not be any requests blocked on this queue it
901 * can not hurt to be paranoid and try to wake up requests that may
902 * haven been blocked when more than 50 at time were on the wire to the
903 * same server - they now will see the session is in exit state and get
904 * out of SendReceive.
905 */
906 wake_up_all(&server->request_q);
907 /* give those requests time to exit */
908 msleep(125);
Long Libce9ce72017-11-22 17:38:38 -0700909 if (cifs_rdma_enabled(server) && server->smbd_conn) {
910 smbd_destroy(server->smbd_conn);
911 server->smbd_conn = NULL;
912 }
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400913 if (server->ssocket) {
914 sock_release(server->ssocket);
915 server->ssocket = NULL;
916 }
917
918 if (!list_empty(&server->pending_mid_q)) {
919 struct list_head dispose_list;
920 struct mid_q_entry *mid_entry;
921 struct list_head *tmp, *tmp2;
922
923 INIT_LIST_HEAD(&dispose_list);
924 spin_lock(&GlobalMid_Lock);
925 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
926 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500927 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400928 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400929 list_move(&mid_entry->qhead, &dispose_list);
930 }
931 spin_unlock(&GlobalMid_Lock);
932
933 /* now walk dispose list and issue callbacks */
934 list_for_each_safe(tmp, tmp2, &dispose_list) {
935 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500936 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400937 list_del_init(&mid_entry->qhead);
938 mid_entry->callback(mid_entry);
939 }
940 /* 1/8th of sec is more than enough time for them to exit */
941 msleep(125);
942 }
943
944 if (!list_empty(&server->pending_mid_q)) {
945 /*
946 * mpx threads have not exited yet give them at least the smb
947 * send timeout time for long ops.
948 *
949 * Due to delays on oplock break requests, we need to wait at
950 * least 45 seconds before giving up on a request getting a
951 * response and going ahead and killing cifsd.
952 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500953 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400954 msleep(46000);
955 /*
956 * If threads still have not exited they are probably never
957 * coming home not much else we can do but free the memory.
958 */
959 }
960
961 kfree(server->hostname);
962 kfree(server);
963
964 length = atomic_dec_return(&tcpSesAllocCount);
965 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700966 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400967}
968
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400969static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400970standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
971{
972 int length;
973 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +1000974 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400975
976 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100977 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
978 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500979 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400980 cifs_reconnect(server);
981 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400982 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400983 }
984
985 /* switch to large buffer if too big for a small one */
986 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
987 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400988 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400989 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400990 }
991
992 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400993 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +1100994 pdu_length - HEADER_SIZE(server) + 1
995 + server->vals->header_preamble_size);
996
Jeff Laytone9097ab2011-10-19 15:29:40 -0400997 if (length < 0)
998 return length;
999 server->total_read += length;
1000
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001001 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001002
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08001003 return cifs_handle_standard(server, mid);
1004}
1005
1006int
1007cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1008{
1009 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1010 int length;
1011
Jeff Laytone9097ab2011-10-19 15:29:40 -04001012 /*
1013 * We know that we received enough to get to the MID as we
1014 * checked the pdu_length earlier. Now check to see
1015 * if the rest of the header is OK. We borrow the length
1016 * var for the rest of the loop to avoid a new stack var.
1017 *
1018 * 48 bytes is enough to display the header and a little bit
1019 * into the payload for debugging purposes.
1020 */
Steve French373512e2015-12-18 13:05:30 -06001021 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001022 if (length != 0)
1023 cifs_dump_mem("Bad SMB: ", buf,
1024 min_t(unsigned int, server->total_read, 48));
1025
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001026 if (server->ops->is_session_expired &&
1027 server->ops->is_session_expired(buf)) {
1028 cifs_reconnect(server);
1029 wake_up(&server->response_q);
1030 return -1;
1031 }
1032
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001033 if (server->ops->is_status_pending &&
1034 server->ops->is_status_pending(buf, server, length))
1035 return -1;
1036
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001037 if (!mid)
1038 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001039
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001040 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001041 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001042}
1043
1044static int
Al Viro7c97c202011-06-21 08:51:28 -04001045cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001047 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001048 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001049 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001050 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001051 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001052 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001053 struct mid_q_entry *mids[MAX_COMPOUND];
1054 char *bufs[MAX_COMPOUND];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -05001057 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001058
1059 length = atomic_inc_return(&tcpSesAllocCount);
1060 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001061 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001063 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +00001064 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001065 if (try_to_freeze())
1066 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001067
Jeff Layton2a37ef92011-10-19 15:29:23 -04001068 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001069 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001070
Jeff Layton2a37ef92011-10-19 15:29:23 -04001071 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001072 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001073 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001074
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001075 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001076 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001077 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001078
1079 if (server->vals->header_preamble_size == 0)
1080 server->total_read = 0;
1081 else
1082 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001083
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001084 /*
1085 * The right amount was read from socket - 4 bytes,
1086 * so we can now interpret the length field.
1087 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001088 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001089
Joe Perchesf96637b2013-05-04 22:12:25 -05001090 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001091 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001092 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001093next_pdu:
1094 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001095
Jeff Layton89482a52011-10-19 15:28:57 -04001096 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001097 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001098 server->vals->header_preamble_size) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001099 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001100 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001101 cifs_reconnect(server);
1102 wake_up(&server->response_q);
1103 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001104 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001105
Jeff Layton89482a52011-10-19 15:28:57 -04001106 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001107 length = cifs_read_from_socket(server,
1108 buf + server->vals->header_preamble_size,
1109 HEADER_SIZE(server) - 1
1110 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001111 if (length < 0)
1112 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001113 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001114
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001115 if (server->ops->next_header) {
1116 next_offset = server->ops->next_header(buf);
1117 if (next_offset)
1118 server->pdu_size = next_offset;
1119 }
1120
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001121 memset(mids, 0, sizeof(mids));
1122 memset(bufs, 0, sizeof(bufs));
1123 num_mids = 0;
1124
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001125 if (server->ops->is_transform_hdr &&
1126 server->ops->receive_transform &&
1127 server->ops->is_transform_hdr(buf)) {
1128 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001129 mids,
1130 bufs,
1131 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001132 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001133 mids[0] = server->ops->find_mid(server, buf);
1134 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001135 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001136
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001137 if (!mids[0] || !mids[0]->receive)
1138 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001139 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001140 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001141 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001142
Lars Persson696e4202018-06-25 14:05:25 +02001143 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001144 for (i = 0; i < num_mids; i++)
1145 if (mids[i])
1146 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001147 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001148 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001149
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001150 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -04001151 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -07001152
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001153
Steve Frenchfda35942011-01-20 18:06:34 +00001154 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001155
1156 for (i = 0; i < num_mids; i++) {
1157 if (mids[i] != NULL) {
1158 mids[i]->resp_buf_size = server->pdu_size;
1159 if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
1160 mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
1161 server->ops->handle_cancelled_mid)
1162 server->ops->handle_cancelled_mid(
1163 mids[i]->resp_buf,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001164 server);
1165
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001166 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1167 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001168
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001169 cifs_mid_q_entry_release(mids[i]);
1170 } else if (server->ops->is_oplock_break &&
1171 server->ops->is_oplock_break(bufs[i],
1172 server)) {
1173 cifs_dbg(FYI, "Received oplock break\n");
1174 } else {
1175 cifs_dbg(VFS, "No task to wake, unknown frame "
1176 "received! NumMids %d\n",
1177 atomic_read(&midCount));
1178 cifs_dump_mem("Received Data is: ", bufs[i],
1179 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +00001180#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001181 if (server->ops->dump_detail)
1182 server->ops->dump_detail(bufs[i],
1183 server);
1184 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001185#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001186 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001187 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001188
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001189 if (pdu_length > server->pdu_size) {
1190 if (!allocate_buffers(server))
1191 continue;
1192 pdu_length -= server->pdu_size;
1193 server->total_read = 0;
1194 server->large_buf = false;
1195 buf = server->smallbuf;
1196 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001197 }
1198 } /* end while !EXITING */
1199
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001200 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001201 cifs_buf_release(server->bigbuf);
1202 if (server->smallbuf) /* no sense logging a debug message if NULL */
1203 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001205 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001206 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001207
1208 /* if server->tsk was NULL then wait for a signal before exiting */
1209 if (!task_to_wake) {
1210 set_current_state(TASK_INTERRUPTIBLE);
1211 while (!signal_pending(current)) {
1212 schedule();
1213 set_current_state(TASK_INTERRUPTIBLE);
1214 }
1215 set_current_state(TASK_RUNNING);
1216 }
1217
Jeff Layton0468a2c2008-12-01 07:09:35 -05001218 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219}
1220
Jeff Laytonc359cf32007-11-16 22:22:06 +00001221/* extract the host portion of the UNC string */
1222static char *
1223extract_hostname(const char *unc)
1224{
1225 const char *src;
1226 char *dst, *delim;
1227 unsigned int len;
1228
1229 /* skip double chars at beginning of string */
1230 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001231 if (strlen(unc) < 3)
1232 return ERR_PTR(-EINVAL);
1233 for (src = unc; *src && *src == '\\'; src++)
1234 ;
1235 if (!*src)
1236 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001237
1238 /* delimiter between hostname and sharename is always '\\' now */
1239 delim = strchr(src, '\\');
1240 if (!delim)
1241 return ERR_PTR(-EINVAL);
1242
1243 len = delim - src;
1244 dst = kmalloc((len + 1), GFP_KERNEL);
1245 if (dst == NULL)
1246 return ERR_PTR(-ENOMEM);
1247
1248 memcpy(dst, src, len);
1249 dst[len] = '\0';
1250
1251 return dst;
1252}
1253
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001254static int get_option_ul(substring_t args[], unsigned long *option)
1255{
1256 int rc;
1257 char *string;
1258
1259 string = match_strdup(args);
1260 if (string == NULL)
1261 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001262 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001263 kfree(string);
1264
1265 return rc;
1266}
1267
Eric W. Biederman3da46562013-02-06 01:37:39 -08001268static int get_option_uid(substring_t args[], kuid_t *result)
1269{
1270 unsigned long value;
1271 kuid_t uid;
1272 int rc;
1273
1274 rc = get_option_ul(args, &value);
1275 if (rc)
1276 return rc;
1277
1278 uid = make_kuid(current_user_ns(), value);
1279 if (!uid_valid(uid))
1280 return -EINVAL;
1281
1282 *result = uid;
1283 return 0;
1284}
1285
1286static int get_option_gid(substring_t args[], kgid_t *result)
1287{
1288 unsigned long value;
1289 kgid_t gid;
1290 int rc;
1291
1292 rc = get_option_ul(args, &value);
1293 if (rc)
1294 return rc;
1295
1296 gid = make_kgid(current_user_ns(), value);
1297 if (!gid_valid(gid))
1298 return -EINVAL;
1299
1300 *result = gid;
1301 return 0;
1302}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001303
1304static int cifs_parse_security_flavors(char *value,
1305 struct smb_vol *vol)
1306{
1307
1308 substring_t args[MAX_OPT_ARGS];
1309
Jeff Layton1e3cc572013-06-10 17:12:23 -05001310 /*
1311 * With mount options, the last one should win. Reset any existing
1312 * settings back to default.
1313 */
1314 vol->sectype = Unspecified;
1315 vol->sign = false;
1316
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001317 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001318 case Opt_sec_krb5p:
1319 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1320 return 1;
1321 case Opt_sec_krb5i:
1322 vol->sign = true;
1323 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001324 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001325 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001326 break;
1327 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001328 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001329 /* Fallthrough */
1330 case Opt_sec_ntlmssp:
1331 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001332 break;
1333 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001334 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001335 /* Fallthrough */
1336 case Opt_ntlm:
1337 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001338 break;
1339 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001340 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001341 /* Fallthrough */
1342 case Opt_sec_ntlmv2:
1343 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001344 break;
1345#ifdef CONFIG_CIFS_WEAK_PW_HASH
1346 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001347 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001348 break;
1349#endif
1350 case Opt_sec_none:
1351 vol->nullauth = 1;
1352 break;
1353 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001354 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001355 return 1;
1356 }
1357
1358 return 0;
1359}
1360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001362cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1363{
1364 substring_t args[MAX_OPT_ARGS];
1365
1366 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1367 case Opt_cache_loose:
1368 vol->direct_io = false;
1369 vol->strict_io = false;
1370 break;
1371 case Opt_cache_strict:
1372 vol->direct_io = false;
1373 vol->strict_io = true;
1374 break;
1375 case Opt_cache_none:
1376 vol->direct_io = true;
1377 vol->strict_io = false;
1378 break;
1379 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001380 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001381 return 1;
1382 }
1383 return 0;
1384}
1385
1386static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001387cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001388{
1389 substring_t args[MAX_OPT_ARGS];
1390
1391 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001392#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001393 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001394 if (disable_legacy_dialects) {
1395 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1396 return 1;
1397 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001398 if (is_smb3) {
1399 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1400 return 1;
1401 }
Jeff Layton23db65f2012-05-15 12:20:51 -04001402 vol->ops = &smb1_operations;
1403 vol->vals = &smb1_values;
1404 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001405 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001406 if (disable_legacy_dialects) {
1407 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1408 return 1;
1409 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001410 if (is_smb3) {
1411 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1412 return 1;
1413 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001414 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001415 vol->vals = &smb20_values;
1416 break;
Steve French74204512018-06-19 14:34:08 -05001417#else
1418 case Smb_1:
1419 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1420 return 1;
1421 case Smb_20:
1422 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1423 return 1;
1424#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001425 case Smb_21:
1426 vol->ops = &smb21_operations;
1427 vol->vals = &smb21_values;
1428 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001429 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001430 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001431 vol->vals = &smb30_values;
1432 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001433 case Smb_302:
1434 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1435 vol->vals = &smb302_values;
1436 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001437 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001438 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001439 vol->vals = &smb311_values;
1440 break;
Steve French9764c022017-09-17 10:41:35 -05001441 case Smb_3any:
1442 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1443 vol->vals = &smb3any_values;
1444 break;
1445 case Smb_default:
1446 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1447 vol->vals = &smbdefault_values;
1448 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001449 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001450 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001451 return 1;
1452 }
1453 return 0;
1454}
1455
Jeff Laytond387a5c2012-12-10 06:10:46 -05001456/*
1457 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1458 * fields with the result. Returns 0 on success and an error otherwise.
1459 */
1460static int
1461cifs_parse_devname(const char *devname, struct smb_vol *vol)
1462{
1463 char *pos;
1464 const char *delims = "/\\";
1465 size_t len;
1466
1467 /* make sure we have a valid UNC double delimiter prefix */
1468 len = strspn(devname, delims);
1469 if (len != 2)
1470 return -EINVAL;
1471
1472 /* find delimiter between host and sharename */
1473 pos = strpbrk(devname + 2, delims);
1474 if (!pos)
1475 return -EINVAL;
1476
1477 /* skip past delimiter */
1478 ++pos;
1479
1480 /* now go until next delimiter or end of string */
1481 len = strcspn(pos, delims);
1482
1483 /* move "pos" up to delimiter or NULL */
1484 pos += len;
1485 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1486 if (!vol->UNC)
1487 return -ENOMEM;
1488
1489 convert_delimiter(vol->UNC, '\\');
1490
Sachin Prabhu11e31642016-02-08 13:44:01 +05301491 /* skip any delimiter */
1492 if (*pos == '/' || *pos == '\\')
1493 pos++;
1494
1495 /* If pos is NULL then no prepath */
1496 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001497 return 0;
1498
1499 vol->prepath = kstrdup(pos, GFP_KERNEL);
1500 if (!vol->prepath)
1501 return -ENOMEM;
1502
1503 return 0;
1504}
1505
Jeff Layton23db65f2012-05-15 12:20:51 -04001506static int
Sean Finneyb9468452011-04-11 13:19:32 +00001507cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001508 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001510 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001511 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 unsigned int temp_len, i, j;
1513 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001514 short int override_uid = -1;
1515 short int override_gid = -1;
1516 bool uid_specified = false;
1517 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001518 bool sloppy = false;
1519 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001520 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001521 char *string = NULL;
1522 char *tmp_end, *value;
1523 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001524 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001525 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001526 unsigned short port = 0;
1527 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528
1529 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001530 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001531 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
Jeff Layton6ee95422012-11-26 11:09:57 -05001533 /* ensure we always start with zeroed-out smb_vol */
1534 memset(vol, 0, sizeof(*vol));
1535
Jeff Layton88463992010-11-22 15:31:03 -05001536 /*
1537 * does not have to be perfect mapping since field is
1538 * informational, only used for servers that do not support
1539 * port 445 and it can be overridden at mount time
1540 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001541 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1542 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001543 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1544
Jeff Layton1397f2e2011-01-07 11:30:28 -05001545 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001546 /* null target name indicates to use *SMBSERVR default called name
1547 if we end up sending RFC1001 session initialize */
1548 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001549 vol->cred_uid = current_uid();
1550 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001551 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001552
Steve French2baa2682014-09-27 02:19:01 -05001553 /*
1554 * default to SFM style remapping of seven reserved characters
1555 * unless user overrides it or we negotiate CIFS POSIX where
1556 * it is unnecessary. Can not simultaneously use more than one mapping
1557 * since then readdir could list files that open could not open
1558 */
1559 vol->remap = true;
1560
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001561 /* default to only allowing write access to owner of the mount */
1562 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
1564 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001565 /* default is always to request posix paths. */
1566 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001567 /* default to using server inode numbers where available */
1568 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001569
Jeff Layton1b359202012-09-19 15:20:27 -07001570 /* default is to use strict cifs caching semantics */
1571 vol->strict_io = true;
1572
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301573 vol->actimeo = CIFS_DEF_ACTIMEO;
1574
Steve French9764c022017-09-17 10:41:35 -05001575 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1576 vol->ops = &smb30_operations;
1577 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001578
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001579 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1580
Sean Finneyb9468452011-04-11 13:19:32 +00001581 if (!mountdata)
1582 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Sean Finneyb9468452011-04-11 13:19:32 +00001584 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1585 if (!mountdata_copy)
1586 goto cifs_parse_mount_err;
1587
1588 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001589 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001590
Steve French50c2f752007-07-13 00:33:32 +00001591 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001592 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 separator[0] = options[4];
1594 options += 5;
1595 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001596 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 }
1598 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001599 vol->backupuid_specified = false; /* no backup intent for a user */
1600 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001601
Jeff Layton37d4f992013-05-24 07:40:05 -04001602 switch (cifs_parse_devname(devname, vol)) {
1603 case 0:
1604 break;
1605 case -ENOMEM:
1606 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1607 goto cifs_parse_mount_err;
1608 case -EINVAL:
1609 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1610 goto cifs_parse_mount_err;
1611 default:
1612 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1613 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001614 }
1615
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001617 substring_t args[MAX_OPT_ARGS];
1618 unsigned long option;
1619 int token;
1620
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 if (!*data)
1622 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001624 token = match_token(data, cifs_mount_option_tokens, args);
1625
1626 switch (token) {
1627
1628 /* Ingnore the following */
1629 case Opt_ignore:
1630 break;
1631
1632 /* Boolean values */
1633 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001635 break;
1636 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001638 break;
1639 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001640 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001641 break;
1642 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001643 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001644 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001645 case Opt_forcegid:
1646 override_gid = 1;
1647 break;
1648 case Opt_noforcegid:
1649 override_gid = 0;
1650 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001651 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001652 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001653 break;
1654 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001655 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001656 break;
1657 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001659 break;
1660 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001662 break;
1663 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001665 break;
1666 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001668 break;
1669 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001670 vol->sfu_remap = true;
1671 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001672 break;
1673 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001674 vol->sfu_remap = false;
1675 break;
1676 case Opt_mapposix:
1677 vol->remap = true;
1678 vol->sfu_remap = false; /* disable SFU mapping */
1679 break;
1680 case Opt_nomapposix:
1681 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001682 break;
1683 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001684 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001685 break;
1686 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001687 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001688 break;
1689 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001690 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001691 break;
1692 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001693 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001694 break;
1695 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001696 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001697 break;
1698 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001699 if (vol->linux_ext)
1700 cifs_dbg(VFS,
1701 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001702 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001703 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001704 case Opt_unix:
1705 if (vol->no_linux_ext)
1706 cifs_dbg(VFS,
1707 "conflicting unix mount options\n");
1708 vol->linux_ext = 1;
1709 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001710 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001711 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001712 break;
1713 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001714 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001715 break;
1716 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001717 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001718 /*
1719 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001720 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001721 * local vfs will do advisory
1722 */
Steve French50c2f752007-07-13 00:33:32 +00001723 if (vol->file_mode ==
1724 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001725 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001726 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001727 case Opt_nohandlecache:
1728 vol->nohandlecache = 1;
1729 break;
1730 case Opt_handlecache:
1731 vol->nohandlecache = 0;
1732 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001733 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001734 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001735 break;
1736 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001738 break;
1739 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001741 break;
Steve French95932652016-09-23 01:36:34 -05001742 case Opt_setuidfromacl:
1743 vol->setuidfromacl = 1;
1744 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001746 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001747 break;
1748 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001749 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001750 break;
1751 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001753 break;
1754 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001756 break;
1757 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001759 break;
1760 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001762 break;
1763 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001764 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001765 break;
1766 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001767 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001768 break;
1769 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001771 break;
1772 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001774 break;
1775 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001776 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001777 break;
1778 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001779 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001780 break;
1781 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001782 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001783 break;
1784 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001786 break;
1787 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001789 break;
1790 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001791 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001792 break;
1793 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001794 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001795 break;
1796 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001797 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001798 * is a per tree connection (mount) not a per socket
1799 * or per-smb connection option in the protocol
1800 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1801 */
Steve French95b1cb92008-05-15 16:44:38 +00001802 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001804 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001805 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001806 break;
1807 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301808#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001809 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001810 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301811#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301812 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001813 break;
1814 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001815 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001816 break;
1817 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001818 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001819 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001820 case Opt_sloppy:
1821 sloppy = true;
1822 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001823 case Opt_nosharesock:
1824 vol->nosharesock = true;
1825 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001826 case Opt_nopersistent:
1827 vol->nopersistent = true;
1828 if (vol->persistent) {
1829 cifs_dbg(VFS,
1830 "persistenthandles mount options conflict\n");
1831 goto cifs_parse_mount_err;
1832 }
1833 break;
1834 case Opt_persistent:
1835 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001836 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001837 cifs_dbg(VFS,
1838 "persistenthandles mount options conflict\n");
1839 goto cifs_parse_mount_err;
1840 }
1841 break;
Steve French592fafe2015-11-03 10:08:53 -06001842 case Opt_resilient:
1843 vol->resilient = true;
1844 if (vol->persistent) {
1845 cifs_dbg(VFS,
1846 "persistenthandles mount options conflict\n");
1847 goto cifs_parse_mount_err;
1848 }
1849 break;
1850 case Opt_noresilient:
1851 vol->resilient = false; /* already the default */
1852 break;
Germano Percossi39566442016-12-15 12:31:18 +05301853 case Opt_domainauto:
1854 vol->domainauto = true;
1855 break;
Long Li8339dd32017-11-07 01:54:55 -07001856 case Opt_rdma:
1857 vol->rdma = true;
1858 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001859
1860 /* Numeric Values */
1861 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001862 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001863 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1864 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001865 goto cifs_parse_mount_err;
1866 }
1867 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001868 break;
1869 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001870 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001871 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1872 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001873 goto cifs_parse_mount_err;
1874 }
1875 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001876 break;
1877 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001878 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001879 cifs_dbg(VFS, "%s: Invalid uid value\n",
1880 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001881 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001883 uid_specified = true;
1884 break;
1885 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001886 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001887 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1888 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001889 goto cifs_parse_mount_err;
1890 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001891 break;
1892 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001893 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001894 cifs_dbg(VFS, "%s: Invalid gid value\n",
1895 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001896 goto cifs_parse_mount_err;
1897 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001898 gid_specified = true;
1899 break;
1900 case Opt_file_mode:
1901 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001902 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1903 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001904 goto cifs_parse_mount_err;
1905 }
1906 vol->file_mode = option;
1907 break;
1908 case Opt_dirmode:
1909 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001910 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1911 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001912 goto cifs_parse_mount_err;
1913 }
1914 vol->dir_mode = option;
1915 break;
1916 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001917 if (get_option_ul(args, &option) ||
1918 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001919 cifs_dbg(VFS, "%s: Invalid port value\n",
1920 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001921 goto cifs_parse_mount_err;
1922 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001923 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001924 break;
1925 case Opt_rsize:
1926 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001927 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1928 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001929 goto cifs_parse_mount_err;
1930 }
1931 vol->rsize = option;
1932 break;
1933 case Opt_wsize:
1934 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001935 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1936 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001937 goto cifs_parse_mount_err;
1938 }
1939 vol->wsize = option;
1940 break;
1941 case Opt_actimeo:
1942 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001943 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1944 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001945 goto cifs_parse_mount_err;
1946 }
1947 vol->actimeo = HZ * option;
1948 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001949 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001950 goto cifs_parse_mount_err;
1951 }
1952 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06001953 case Opt_echo_interval:
1954 if (get_option_ul(args, &option)) {
1955 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
1956 __func__);
1957 goto cifs_parse_mount_err;
1958 }
1959 vol->echo_interval = option;
1960 break;
Steve French8b217fe2016-11-11 22:36:20 -06001961 case Opt_snapshot:
1962 if (get_option_ul(args, &option)) {
1963 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
1964 __func__);
1965 goto cifs_parse_mount_err;
1966 }
1967 vol->snapshot_time = option;
1968 break;
Steve French141891f2016-09-23 00:44:16 -05001969 case Opt_max_credits:
1970 if (get_option_ul(args, &option) || (option < 20) ||
1971 (option > 60000)) {
1972 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1973 __func__);
1974 goto cifs_parse_mount_err;
1975 }
1976 vol->max_credits = option;
1977 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001978
1979 /* String Arguments */
1980
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001981 case Opt_blank_user:
1982 /* null user, ie. anonymous authentication */
1983 vol->nullauth = 1;
1984 vol->username = NULL;
1985 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001986 case Opt_user:
1987 string = match_strdup(args);
1988 if (string == NULL)
1989 goto out_nomem;
1990
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001991 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1992 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001993 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001994 goto cifs_parse_mount_err;
1995 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001996
1997 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001998 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001999 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002000 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002001 break;
2002 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002003 /* passwords have to be handled differently
2004 * to allow the character used for deliminator
2005 * to be passed within them
2006 */
2007
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002008 /*
2009 * Check if this is a case where the password
2010 * starts with a delimiter
2011 */
2012 tmp_end = strchr(data, '=');
2013 tmp_end++;
2014 if (!(tmp_end < end && tmp_end[1] == delim)) {
2015 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002016 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002017 vol->password = NULL;
2018 break;
2019 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +11002020 /* Fallthrough - to Opt_pass below.*/
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002021 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002022 /* Obtain the value string */
2023 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002024 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002025
2026 /* Set tmp_end to end of the string */
2027 tmp_end = (char *) value + strlen(value);
2028
2029 /* Check if following character is the deliminator
2030 * If yes, we have encountered a double deliminator
2031 * reset the NULL character to the deliminator
2032 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302033 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002034 tmp_end[0] = delim;
2035
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302036 /* Keep iterating until we get to a single
2037 * deliminator OR the end
2038 */
2039 while ((tmp_end = strchr(tmp_end, delim))
2040 != NULL && (tmp_end[1] == delim)) {
2041 tmp_end = (char *) &tmp_end[2];
2042 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002043
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302044 /* Reset var options to point to next element */
2045 if (tmp_end) {
2046 tmp_end[0] = '\0';
2047 options = (char *) &tmp_end[1];
2048 } else
2049 /* Reached the end of the mount option
2050 * string */
2051 options = end;
2052 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002053
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002054 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002055 /* Now build new password string */
2056 temp_len = strlen(value);
2057 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2058 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002059 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002060 goto cifs_parse_mount_err;
2061 }
2062
2063 for (i = 0, j = 0; i < temp_len; i++, j++) {
2064 vol->password[j] = value[i];
2065 if ((value[i] == delim) &&
2066 value[i+1] == delim)
2067 /* skip the second deliminator */
2068 i++;
2069 }
2070 vol->password[j] = '\0';
2071 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002072 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002073 /* FIXME: should this be an error instead? */
2074 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002075 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002076 case Opt_ip:
2077 string = match_strdup(args);
2078 if (string == NULL)
2079 goto out_nomem;
2080
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002081 if (!cifs_convert_address(dstaddr, string,
2082 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002083 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002084 goto cifs_parse_mount_err;
2085 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002086 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002087 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002088 case Opt_domain:
2089 string = match_strdup(args);
2090 if (string == NULL)
2091 goto out_nomem;
2092
Chen Gang057d6332013-07-19 09:01:36 +08002093 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2094 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002095 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002096 goto cifs_parse_mount_err;
2097 }
2098
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002099 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002100 vol->domainname = kstrdup(string, GFP_KERNEL);
2101 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002102 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002103 goto cifs_parse_mount_err;
2104 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002105 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002106 break;
2107 case Opt_srcaddr:
2108 string = match_strdup(args);
2109 if (string == NULL)
2110 goto out_nomem;
2111
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002112 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002113 (struct sockaddr *)&vol->srcaddr,
2114 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002115 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2116 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002117 goto cifs_parse_mount_err;
2118 }
2119 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002120 case Opt_iocharset:
2121 string = match_strdup(args);
2122 if (string == NULL)
2123 goto out_nomem;
2124
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002125 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002126 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002127 goto cifs_parse_mount_err;
2128 }
2129
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002130 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002131 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002132 vol->iocharset = kstrdup(string,
2133 GFP_KERNEL);
2134 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002135 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002136 goto cifs_parse_mount_err;
2137 }
2138 }
2139 /* if iocharset not set then load_nls_default
2140 * is used by caller
2141 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002142 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002143 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002144 case Opt_netbiosname:
2145 string = match_strdup(args);
2146 if (string == NULL)
2147 goto out_nomem;
2148
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002149 memset(vol->source_rfc1001_name, 0x20,
2150 RFC1001_NAME_LEN);
2151 /*
2152 * FIXME: are there cases in which a comma can
2153 * be valid in workstation netbios name (and
2154 * need special handling)?
2155 */
2156 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2157 /* don't ucase netbiosname for user */
2158 if (string[i] == 0)
2159 break;
2160 vol->source_rfc1001_name[i] = string[i];
2161 }
2162 /* The string has 16th byte zero still from
2163 * set at top of the function
2164 */
2165 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002166 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002167 break;
2168 case Opt_servern:
2169 /* servernetbiosname specified override *SMBSERVER */
2170 string = match_strdup(args);
2171 if (string == NULL)
2172 goto out_nomem;
2173
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002174 /* last byte, type, is 0x20 for servr type */
2175 memset(vol->target_rfc1001_name, 0x20,
2176 RFC1001_NAME_LEN_WITH_NULL);
2177
2178 /* BB are there cases in which a comma can be
2179 valid in this workstation netbios name
2180 (and need special handling)? */
2181
2182 /* user or mount helper must uppercase the
2183 netbios name */
2184 for (i = 0; i < 15; i++) {
2185 if (string[i] == 0)
2186 break;
2187 vol->target_rfc1001_name[i] = string[i];
2188 }
2189 /* The string has 16th byte zero still from
2190 set at top of the function */
2191 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002192 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002193 break;
2194 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002195 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002196 string = match_strdup(args);
2197 if (string == NULL)
2198 goto out_nomem;
2199
Steve French7e682f72017-08-31 21:34:24 -05002200 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002201 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002202 if (strlen(string) > 1) {
2203 pr_warn("Bad mount helper ver=%s. Did "
2204 "you want SMB1 (CIFS) dialect "
2205 "and mean to type vers=1.0 "
2206 "instead?\n", string);
2207 goto cifs_parse_mount_err;
2208 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002209 /* This is the default */
2210 break;
2211 }
2212 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05002213 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002214 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002215 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002216 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002217 string = match_strdup(args);
2218 if (string == NULL)
2219 goto out_nomem;
2220
Steve Frenchc7c137b2018-06-06 17:59:29 -05002221 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002222 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002223 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002224 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002225 case Opt_sec:
2226 string = match_strdup(args);
2227 if (string == NULL)
2228 goto out_nomem;
2229
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002230 if (cifs_parse_security_flavors(string, vol) != 0)
2231 goto cifs_parse_mount_err;
2232 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002233 case Opt_cache:
2234 string = match_strdup(args);
2235 if (string == NULL)
2236 goto out_nomem;
2237
2238 if (cifs_parse_cache_flavor(string, vol) != 0)
2239 goto cifs_parse_mount_err;
2240 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002241 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002242 /*
2243 * An option we don't recognize. Save it off for later
2244 * if we haven't already found one
2245 */
2246 if (!invalid)
2247 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002248 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002250 /* Free up any allocated string */
2251 kfree(string);
2252 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002254
Jeff Laytond8162552012-03-23 14:40:56 -04002255 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002256 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002257 goto cifs_parse_mount_err;
2258 }
2259
Long Li8339dd32017-11-07 01:54:55 -07002260 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2261 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2262 goto cifs_parse_mount_err;
2263 }
2264
Jeff Layton8a8798a2012-01-17 16:09:15 -05002265#ifndef CONFIG_KEYS
2266 /* Muliuser mounts require CONFIG_KEYS support */
2267 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002268 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002269 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002270 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002271#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002272 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002273 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002274 goto cifs_parse_mount_err;
2275 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002276
Jeff Layton62a1a432012-12-10 06:10:45 -05002277 /* make sure UNC has a share name */
2278 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002279 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002280 goto cifs_parse_mount_err;
2281 }
2282
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002283 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002284 int len;
2285 const char *slash;
2286
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002287 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002288 /* Use the address part of the UNC. */
2289 slash = strchr(&vol->UNC[2], '\\');
2290 len = slash - &vol->UNC[2];
2291 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002292 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002293 goto cifs_parse_mount_err;
2294 }
2295 }
2296
2297 /* set the port that we got earlier */
2298 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002300 if (uid_specified)
2301 vol->override_uid = override_uid;
2302 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002303 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002304
2305 if (gid_specified)
2306 vol->override_gid = override_gid;
2307 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002308 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002309
Steve French7e682f72017-08-31 21:34:24 -05002310 if (got_version == false)
2311 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002312 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002313 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002314 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2315 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002316
Sean Finneyb9468452011-04-11 13:19:32 +00002317 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002319
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002320out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002321 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002322cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002323 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002324 kfree(mountdata_copy);
2325 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326}
2327
Ben Greear3eb9a882010-09-01 17:06:02 -07002328/** Returns true if srcaddr isn't specified and rhs isn't
2329 * specified, or if srcaddr is specified and
2330 * matches the IP address of the rhs argument.
2331 */
Jeff Layton45151482010-07-06 20:43:02 -04002332static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002333srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2334{
2335 switch (srcaddr->sa_family) {
2336 case AF_UNSPEC:
2337 return (rhs->sa_family == AF_UNSPEC);
2338 case AF_INET: {
2339 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2340 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2341 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2342 }
2343 case AF_INET6: {
2344 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002345 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002346 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2347 }
2348 default:
2349 WARN_ON(1);
2350 return false; /* don't expect to be here */
2351 }
2352}
2353
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002354/*
2355 * If no port is specified in addr structure, we try to match with 445 port
2356 * and if it fails - with 139 ports. It should be called only if address
2357 * families of server and addr are equal.
2358 */
2359static bool
2360match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2361{
Steve French6da97912011-03-13 18:55:55 +00002362 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002363
2364 switch (addr->sa_family) {
2365 case AF_INET:
2366 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2367 port = ((struct sockaddr_in *) addr)->sin_port;
2368 break;
2369 case AF_INET6:
2370 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2371 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2372 break;
2373 default:
2374 WARN_ON(1);
2375 return false;
2376 }
2377
2378 if (!port) {
2379 port = htons(CIFS_PORT);
2380 if (port == *sport)
2381 return true;
2382
2383 port = htons(RFC1001_PORT);
2384 }
2385
2386 return port == *sport;
2387}
Ben Greear3eb9a882010-09-01 17:06:02 -07002388
2389static bool
2390match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2391 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392{
Jeff Layton45151482010-07-06 20:43:02 -04002393 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002394 case AF_INET: {
2395 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2396 struct sockaddr_in *srv_addr4 =
2397 (struct sockaddr_in *)&server->dstaddr;
2398
2399 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002400 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002401 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002402 }
2403 case AF_INET6: {
2404 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2405 struct sockaddr_in6 *srv_addr6 =
2406 (struct sockaddr_in6 *)&server->dstaddr;
2407
Jeff Layton45151482010-07-06 20:43:02 -04002408 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002409 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002410 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002411 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002412 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002413 break;
2414 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002415 default:
2416 WARN_ON(1);
2417 return false; /* don't expect to be here */
2418 }
Jeff Layton45151482010-07-06 20:43:02 -04002419
Ben Greear3eb9a882010-09-01 17:06:02 -07002420 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2421 return false;
2422
Jeff Layton45151482010-07-06 20:43:02 -04002423 return true;
2424}
2425
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002426static bool
2427match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2428{
Jeff Layton3f618222013-06-12 19:52:14 -05002429 /*
2430 * The select_sectype function should either return the vol->sectype
2431 * that was specified, or "Unspecified" if that sectype was not
2432 * compatible with the given NEGOTIATE request.
2433 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302434 if (server->ops->select_sectype(server, vol->sectype)
2435 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002436 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002437
Jeff Layton3f618222013-06-12 19:52:14 -05002438 /*
2439 * Now check if signing mode is acceptable. No need to check
2440 * global_secflags at this point since if MUST_SIGN is set then
2441 * the server->sign had better be too.
2442 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002443 if (vol->sign && !server->sign)
2444 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002445
2446 return true;
2447}
2448
Jeff Layton9fa114f2012-11-26 11:09:57 -05002449static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002450{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002451 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2452
Jeff Laytona0b3df52013-05-24 07:40:59 -04002453 if (vol->nosharesock)
2454 return 0;
2455
Steve French9764c022017-09-17 10:41:35 -05002456 /* BB update this for smb3any and default case */
Jeff Layton23db65f2012-05-15 12:20:51 -04002457 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2458 return 0;
2459
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002460 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2461 return 0;
2462
2463 if (!match_address(server, addr,
2464 (struct sockaddr *)&vol->srcaddr))
2465 return 0;
2466
2467 if (!match_port(server, addr))
2468 return 0;
2469
2470 if (!match_security(server, vol))
2471 return 0;
2472
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002473 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002474 return 0;
2475
Long Li8339dd32017-11-07 01:54:55 -07002476 if (server->rdma != vol->rdma)
2477 return 0;
2478
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002479 return 1;
2480}
2481
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002482struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002483cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002484{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002485 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302487 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002488 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002489 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002490 continue;
2491
Jeff Laytone7ddee92008-11-14 13:44:38 -05002492 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302493 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002494 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002495 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302497 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 return NULL;
2499}
2500
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002501void
2502cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002504 struct task_struct *task;
2505
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302506 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002507 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302508 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002509 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002511
Rob Landleyf1d0c992011-01-22 15:44:05 -06002512 put_net(cifs_net_ns(server));
2513
Jeff Laytone7ddee92008-11-14 13:44:38 -05002514 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302515 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002516
Jeff Laytonc74093b2011-01-11 07:24:23 -05002517 cancel_delayed_work_sync(&server->echo);
2518
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002519 if (from_reconnect)
2520 /*
2521 * Avoid deadlock here: reconnect work calls
2522 * cifs_put_tcp_session() at its end. Need to be sure
2523 * that reconnect work does nothing with server pointer after
2524 * that step.
2525 */
2526 cancel_delayed_work(&server->reconnect);
2527 else
2528 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002529
Jeff Laytone7ddee92008-11-14 13:44:38 -05002530 spin_lock(&GlobalMid_Lock);
2531 server->tcpStatus = CifsExiting;
2532 spin_unlock(&GlobalMid_Lock);
2533
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002534 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302535 cifs_fscache_release_client_cookie(server);
2536
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002537 kfree(server->session_key.response);
2538 server->session_key.response = NULL;
2539 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002540
2541 task = xchg(&server->tsk, NULL);
2542 if (task)
2543 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544}
2545
Jeff Layton63c038c2008-12-01 18:41:46 -05002546static struct TCP_Server_Info *
2547cifs_get_tcp_session(struct smb_vol *volume_info)
2548{
2549 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002550 int rc;
2551
Joe Perchesf96637b2013-05-04 22:12:25 -05002552 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002553
2554 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002555 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002556 if (tcp_ses)
2557 return tcp_ses;
2558
2559 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2560 if (!tcp_ses) {
2561 rc = -ENOMEM;
2562 goto out_err;
2563 }
2564
Jeff Layton23db65f2012-05-15 12:20:51 -04002565 tcp_ses->ops = volume_info->ops;
2566 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002567 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002568 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2569 if (IS_ERR(tcp_ses->hostname)) {
2570 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002571 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002572 }
2573
2574 tcp_ses->noblocksnd = volume_info->noblocksnd;
2575 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002576 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002577 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002578 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002579 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002580 init_waitqueue_head(&tcp_ses->response_q);
2581 init_waitqueue_head(&tcp_ses->request_q);
2582 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2583 mutex_init(&tcp_ses->srv_mutex);
2584 memcpy(tcp_ses->workstation_RFC1001_name,
2585 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2586 memcpy(tcp_ses->server_RFC1001_name,
2587 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002588 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002589 tcp_ses->sequence_number = 0;
Steve French9e1a37d2018-09-19 02:38:17 -05002590 tcp_ses->reconnect_instance = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002591 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002592 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002593 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2594 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002595 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002596 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2597 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002598 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2599 sizeof(tcp_ses->srcaddr));
2600 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2601 sizeof(tcp_ses->dstaddr));
Steve Frenchfa70b872016-09-22 00:39:34 -05002602 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002603 /*
2604 * at this point we are the only ones with the pointer
2605 * to the struct since the kernel thread not created yet
2606 * no need to spinlock this init of tcpStatus or srv_count
2607 */
2608 tcp_ses->tcpStatus = CifsNew;
2609 ++tcp_ses->srv_count;
2610
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002611 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2612 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2613 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2614 else
2615 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002616 if (tcp_ses->rdma) {
2617#ifndef CONFIG_CIFS_SMB_DIRECT
2618 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2619 rc = -ENOENT;
2620 goto out_err_crypto_release;
2621#endif
2622 tcp_ses->smbd_conn = smbd_get_connection(
2623 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2624 if (tcp_ses->smbd_conn) {
2625 cifs_dbg(VFS, "RDMA transport established\n");
2626 rc = 0;
2627 goto smbd_connected;
2628 } else {
2629 rc = -ENOENT;
2630 goto out_err_crypto_release;
2631 }
2632 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002633 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002634 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002635 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002636 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002637 }
Long Li2f894642017-11-22 17:38:34 -07002638smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002639 /*
2640 * since we're in a cifs function already, we know that
2641 * this will succeed. No need for try_module_get().
2642 */
2643 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002644 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002645 tcp_ses, "cifsd");
2646 if (IS_ERR(tcp_ses->tsk)) {
2647 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002648 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002649 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002650 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002651 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002652 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002653
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002654 tcp_ses->nr_targets = 1;
2655
Jeff Layton63c038c2008-12-01 18:41:46 -05002656 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302657 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002658 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302659 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002660
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302661 cifs_fscache_get_client_cookie(tcp_ses);
2662
Jeff Laytonc74093b2011-01-11 07:24:23 -05002663 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002664 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002665
Jeff Layton63c038c2008-12-01 18:41:46 -05002666 return tcp_ses;
2667
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002668out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002669 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002670
Rob Landleyf1d0c992011-01-22 15:44:05 -06002671 put_net(cifs_net_ns(tcp_ses));
2672
Jeff Layton63c038c2008-12-01 18:41:46 -05002673out_err:
2674 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002675 if (!IS_ERR(tcp_ses->hostname))
2676 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002677 if (tcp_ses->ssocket)
2678 sock_release(tcp_ses->ssocket);
2679 kfree(tcp_ses);
2680 }
2681 return ERR_PTR(rc);
2682}
2683
Steve French96daf2b2011-05-27 04:34:02 +00002684static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002685{
Jeff Layton3f618222013-06-12 19:52:14 -05002686 if (vol->sectype != Unspecified &&
2687 vol->sectype != ses->sectype)
2688 return 0;
2689
2690 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002691 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002692 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002693 return 0;
2694 break;
2695 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002696 /* NULL username means anonymous session */
2697 if (ses->user_name == NULL) {
2698 if (!vol->nullauth)
2699 return 0;
2700 break;
2701 }
2702
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002703 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002704 if (strncmp(ses->user_name,
2705 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002706 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002707 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002708 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002709 ses->password != NULL &&
2710 strncmp(ses->password,
2711 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002712 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002713 return 0;
2714 }
2715 return 1;
2716}
2717
Aurelien Aptelb327a712018-01-24 13:46:10 +01002718/**
2719 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2720 *
2721 * A new IPC connection is made and stored in the session
2722 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2723 */
2724static int
2725cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2726{
2727 int rc = 0, xid;
2728 struct cifs_tcon *tcon;
2729 struct nls_table *nls_codepage;
2730 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2731 bool seal = false;
2732
2733 /*
2734 * If the mount request that resulted in the creation of the
2735 * session requires encryption, force IPC to be encrypted too.
2736 */
2737 if (volume_info->seal) {
2738 if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
2739 seal = true;
2740 else {
2741 cifs_dbg(VFS,
2742 "IPC: server doesn't support encryption\n");
2743 return -EOPNOTSUPP;
2744 }
2745 }
2746
2747 tcon = tconInfoAlloc();
2748 if (tcon == NULL)
2749 return -ENOMEM;
2750
Thomas Werschlein395a2072018-08-30 18:29:20 +02002751 snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002752
2753 /* cannot fail */
2754 nls_codepage = load_nls_default();
2755
2756 xid = get_xid();
2757 tcon->ses = ses;
2758 tcon->ipc = true;
2759 tcon->seal = seal;
2760 rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
2761 free_xid(xid);
2762
2763 if (rc) {
2764 cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
2765 tconInfoFree(tcon);
2766 goto out;
2767 }
2768
2769 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2770
2771 ses->tcon_ipc = tcon;
2772out:
2773 unload_nls(nls_codepage);
2774 return rc;
2775}
2776
2777/**
2778 * cifs_free_ipc - helper to release the session IPC tcon
2779 *
2780 * Needs to be called everytime a session is destroyed
2781 */
2782static int
2783cifs_free_ipc(struct cifs_ses *ses)
2784{
2785 int rc = 0, xid;
2786 struct cifs_tcon *tcon = ses->tcon_ipc;
2787
2788 if (tcon == NULL)
2789 return 0;
2790
2791 if (ses->server->ops->tree_disconnect) {
2792 xid = get_xid();
2793 rc = ses->server->ops->tree_disconnect(xid, tcon);
2794 free_xid(xid);
2795 }
2796
2797 if (rc)
2798 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
2799
2800 tconInfoFree(tcon);
2801 ses->tcon_ipc = NULL;
2802 return rc;
2803}
2804
Steve French96daf2b2011-05-27 04:34:02 +00002805static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002806cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807{
Steve French96daf2b2011-05-27 04:34:02 +00002808 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302810 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002811 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002812 if (ses->status == CifsExiting)
2813 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002814 if (!match_session(ses, vol))
2815 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002816 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302817 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002818 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302820 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 return NULL;
2822}
2823
Jeff Layton14fbf502008-11-14 13:53:46 -05002824static void
Steve French96daf2b2011-05-27 04:34:02 +00002825cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002826{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002827 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002828 struct TCP_Server_Info *server = ses->server;
2829
Joe Perchesf96637b2013-05-04 22:12:25 -05002830 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002831
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302832 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002833 if (ses->status == CifsExiting) {
2834 spin_unlock(&cifs_tcp_ses_lock);
2835 return;
2836 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002837 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302838 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002839 return;
2840 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002841 if (ses->status == CifsGood)
2842 ses->status = CifsExiting;
2843 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002844
Aurelien Aptelb327a712018-01-24 13:46:10 +01002845 cifs_free_ipc(ses);
2846
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002847 if (ses->status == CifsExiting && server->ops->logoff) {
2848 xid = get_xid();
2849 rc = server->ops->logoff(xid, ses);
2850 if (rc)
2851 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2852 __func__, rc);
2853 _free_xid(xid);
2854 }
2855
2856 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002857 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302858 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002859
Jeff Layton14fbf502008-11-14 13:53:46 -05002860 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002861 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05002862}
2863
Jeff Layton8a8798a2012-01-17 16:09:15 -05002864#ifdef CONFIG_KEYS
2865
Chen Gang057d6332013-07-19 09:01:36 +08002866/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2867#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002868
2869/* Populate username and pw fields from keyring if possible */
2870static int
2871cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2872{
2873 int rc = 0;
David Howells146aa8b2015-10-21 14:04:48 +01002874 const char *delim, *payload;
2875 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002876 ssize_t len;
2877 struct key *key;
2878 struct TCP_Server_Info *server = ses->server;
2879 struct sockaddr_in *sa;
2880 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01002881 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002882
2883 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2884 if (!desc)
2885 return -ENOMEM;
2886
2887 /* try to find an address key first */
2888 switch (server->dstaddr.ss_family) {
2889 case AF_INET:
2890 sa = (struct sockaddr_in *)&server->dstaddr;
2891 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2892 break;
2893 case AF_INET6:
2894 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2895 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2896 break;
2897 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002898 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2899 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002900 rc = -EINVAL;
2901 goto out_err;
2902 }
2903
Joe Perchesf96637b2013-05-04 22:12:25 -05002904 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002905 key = request_key(&key_type_logon, desc, "");
2906 if (IS_ERR(key)) {
2907 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002908 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002909 rc = PTR_ERR(key);
2910 goto out_err;
2911 }
2912
2913 /* didn't work, try to find a domain key */
2914 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002915 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002916 key = request_key(&key_type_logon, desc, "");
2917 if (IS_ERR(key)) {
2918 rc = PTR_ERR(key);
2919 goto out_err;
2920 }
2921 }
2922
2923 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00002924 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002925 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002926 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002927 goto out_key_put;
2928 }
2929
2930 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01002931 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002932 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002933 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002934 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002935 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2936 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002937 rc = -EINVAL;
2938 goto out_key_put;
2939 }
2940
2941 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002942 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002943 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2944 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002945 rc = -EINVAL;
2946 goto out_key_put;
2947 }
2948
2949 vol->username = kstrndup(payload, len, GFP_KERNEL);
2950 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002951 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2952 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002953 rc = -ENOMEM;
2954 goto out_key_put;
2955 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002956 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002957
2958 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002959 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002960 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002961 rc = -EINVAL;
2962 kfree(vol->username);
2963 vol->username = NULL;
2964 goto out_key_put;
2965 }
2966
2967 ++delim;
2968 vol->password = kstrndup(delim, len, GFP_KERNEL);
2969 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002970 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2971 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002972 rc = -ENOMEM;
2973 kfree(vol->username);
2974 vol->username = NULL;
2975 goto out_key_put;
2976 }
2977
2978out_key_put:
2979 up_read(&key->sem);
2980 key_put(key);
2981out_err:
2982 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002983 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002984 return rc;
2985}
2986#else /* ! CONFIG_KEYS */
2987static inline int
2988cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2989 struct cifs_ses *ses __attribute__((unused)))
2990{
2991 return -ENOSYS;
2992}
2993#endif /* CONFIG_KEYS */
2994
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01002995/**
2996 * cifs_get_smb_ses - get a session matching @volume_info data from @server
2997 *
2998 * This function assumes it is being called from cifs_mount() where we
2999 * already got a server reference (server refcount +1). See
3000 * cifs_get_tcon() for refcount explanations.
3001 */
Steve French96daf2b2011-05-27 04:34:02 +00003002static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04003003cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3004{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003005 int rc = -ENOMEM;
3006 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003007 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003008 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3009 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04003010
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003011 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04003012
Jeff Layton4ff67b72010-07-06 20:43:02 -04003013 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04003014 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003015 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3016 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04003017
Jeff Layton36988c72010-04-24 07:57:43 -04003018 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003019 rc = cifs_negotiate_protocol(xid, ses);
3020 if (rc) {
3021 mutex_unlock(&ses->session_mutex);
3022 /* problem -- put our ses reference */
3023 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003024 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003025 return ERR_PTR(rc);
3026 }
Jeff Layton36988c72010-04-24 07:57:43 -04003027 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003028 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003029 rc = cifs_setup_session(xid, ses,
3030 volume_info->local_nls);
3031 if (rc) {
3032 mutex_unlock(&ses->session_mutex);
3033 /* problem -- put our reference */
3034 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003035 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003036 return ERR_PTR(rc);
3037 }
3038 }
3039 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003040
3041 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003042 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003043 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003044 return ses;
3045 }
3046
Joe Perchesf96637b2013-05-04 22:12:25 -05003047 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003048 ses = sesInfoAlloc();
3049 if (ses == NULL)
3050 goto get_ses_fail;
3051
3052 /* new SMB session uses our server ref */
3053 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003054 if (server->dstaddr.ss_family == AF_INET6)
3055 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003056 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003057 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003058
Steve French8727c8a2011-02-25 01:11:56 -06003059 if (volume_info->username) {
3060 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3061 if (!ses->user_name)
3062 goto get_ses_fail;
3063 }
Jeff Layton36988c72010-04-24 07:57:43 -04003064
3065 /* volume_info->password freed at unmount */
3066 if (volume_info->password) {
3067 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3068 if (!ses->password)
3069 goto get_ses_fail;
3070 }
3071 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003072 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3073 if (!ses->domainName)
3074 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003075 }
Germano Percossi39566442016-12-15 12:31:18 +05303076 if (volume_info->domainauto)
3077 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003078 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003079 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003080
Jeff Layton28e11bd2013-05-26 07:01:00 -04003081 ses->sectype = volume_info->sectype;
3082 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003083
3084 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003085 rc = cifs_negotiate_protocol(xid, ses);
3086 if (!rc)
3087 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04003088 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003089 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003090 goto get_ses_fail;
3091
3092 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303093 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003094 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303095 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003096
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003097 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003098
3099 cifs_setup_ipc(ses, volume_info);
3100
Jeff Layton36988c72010-04-24 07:57:43 -04003101 return ses;
3102
3103get_ses_fail:
3104 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003105 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003106 return ERR_PTR(rc);
3107}
3108
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003109static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003110{
3111 if (tcon->tidStatus == CifsExiting)
3112 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003113 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003114 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003115 if (tcon->seal != volume_info->seal)
3116 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003117 if (tcon->snapshot_time != volume_info->snapshot_time)
3118 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003119 return 1;
3120}
3121
Steve French96daf2b2011-05-27 04:34:02 +00003122static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003123cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124{
3125 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003126 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303128 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003129 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003130 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003131 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003132 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003133 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303134 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 return tcon;
3136 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303137 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 return NULL;
3139}
3140
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003141void
Steve French96daf2b2011-05-27 04:34:02 +00003142cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003143{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003144 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003145 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003146
Aurelien Aptelb327a712018-01-24 13:46:10 +01003147 /*
3148 * IPC tcon share the lifetime of their session and are
3149 * destroyed in the session put function
3150 */
3151 if (tcon == NULL || tcon->ipc)
3152 return;
3153
3154 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003155 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303156 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003157 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303158 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003159 return;
3160 }
3161
3162 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303163 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003164
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003165 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003166 if (ses->server->ops->tree_disconnect)
3167 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003168 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003169
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303170 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003171 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003172 cifs_put_smb_ses(ses);
3173}
3174
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003175/**
3176 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3177 *
3178 * - tcon refcount is the number of mount points using the tcon.
3179 * - ses refcount is the number of tcon using the session.
3180 *
3181 * 1. This function assumes it is being called from cifs_mount() where
3182 * we already got a session reference (ses refcount +1).
3183 *
3184 * 2. Since we're in the context of adding a mount point, the end
3185 * result should be either:
3186 *
3187 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3188 * its session refcount incremented (1 new tcon). This +1 was
3189 * already done in (1).
3190 *
3191 * b) an existing tcon with refcount+1 (add a mount point to it) and
3192 * identical ses refcount (no new tcon). Because of (1) we need to
3193 * decrement the ses refcount.
3194 */
Steve French96daf2b2011-05-27 04:34:02 +00003195static struct cifs_tcon *
3196cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003197{
3198 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003199 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003200
Steve French8b217fe2016-11-11 22:36:20 -06003201 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003202 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003203 /*
3204 * tcon has refcount already incremented but we need to
3205 * decrement extra ses reference gotten by caller (case b)
3206 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003207 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003208 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003209 return tcon;
3210 }
3211
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003212 if (!ses->server->ops->tree_connect) {
3213 rc = -ENOSYS;
3214 goto out_fail;
3215 }
3216
Jeff Laytond00c28d2010-04-24 07:57:44 -04003217 tcon = tconInfoAlloc();
3218 if (tcon == NULL) {
3219 rc = -ENOMEM;
3220 goto out_fail;
3221 }
3222
Steve French8b217fe2016-11-11 22:36:20 -06003223 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003224 if (ses->server->vals->protocol_id == 0) {
3225 cifs_dbg(VFS,
3226 "Use SMB2 or later for snapshot mount option\n");
3227 rc = -EOPNOTSUPP;
3228 goto out_fail;
3229 } else
3230 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003231 }
3232
Jeff Laytond00c28d2010-04-24 07:57:44 -04003233 tcon->ses = ses;
3234 if (volume_info->password) {
3235 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3236 if (!tcon->password) {
3237 rc = -ENOMEM;
3238 goto out_fail;
3239 }
3240 }
3241
Steve French23657ad2018-04-22 15:14:58 -05003242 if (volume_info->seal) {
3243 if (ses->server->vals->protocol_id == 0) {
3244 cifs_dbg(VFS,
3245 "SMB3 or later required for encryption\n");
3246 rc = -EOPNOTSUPP;
3247 goto out_fail;
3248 } else if (tcon->ses->server->capabilities &
3249 SMB2_GLOBAL_CAP_ENCRYPTION)
3250 tcon->seal = true;
3251 else {
3252 cifs_dbg(VFS, "Encryption is not supported on share\n");
3253 rc = -EOPNOTSUPP;
3254 goto out_fail;
3255 }
3256 }
3257
Steve French8505c8b2018-06-18 14:01:59 -05003258 if (volume_info->linux_ext) {
3259 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003260 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003261 printk_once(KERN_WARNING
3262 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003263 } else {
3264 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3265 rc = -EOPNOTSUPP;
3266 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003267 }
Steve Frenchb3266142018-05-20 23:41:10 -05003268 }
Steve Frenchb3266142018-05-20 23:41:10 -05003269
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003270 /*
3271 * BB Do we need to wrap session_mutex around this TCon call and Unix
3272 * SetFS as we do on SessSetup and reconnect?
3273 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003274 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003275 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3276 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003277 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003278 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003279 if (rc)
3280 goto out_fail;
3281
Steve Frenchb618f002015-11-03 09:15:03 -06003282 tcon->use_persistent = false;
3283 /* check if SMB2 or later, CIFS does not support persistent handles */
3284 if (volume_info->persistent) {
3285 if (ses->server->vals->protocol_id == 0) {
3286 cifs_dbg(VFS,
3287 "SMB3 or later required for persistent handles\n");
3288 rc = -EOPNOTSUPP;
3289 goto out_fail;
3290 } else if (ses->server->capabilities &
3291 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3292 tcon->use_persistent = true;
3293 else /* persistent handles requested but not supported */ {
3294 cifs_dbg(VFS,
3295 "Persistent handles not supported on share\n");
3296 rc = -EOPNOTSUPP;
3297 goto out_fail;
3298 }
3299 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3300 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3301 && (volume_info->nopersistent == false)) {
3302 cifs_dbg(FYI, "enabling persistent handles\n");
3303 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003304 } else if (volume_info->resilient) {
3305 if (ses->server->vals->protocol_id == 0) {
3306 cifs_dbg(VFS,
3307 "SMB2.1 or later required for resilient handles\n");
3308 rc = -EOPNOTSUPP;
3309 goto out_fail;
3310 }
3311 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003312 }
3313
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003314 /*
3315 * We can have only one retry value for a connection to a share so for
3316 * resources mounted more than once to the same server share the last
3317 * value passed in for the retry flag is used.
3318 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003319 tcon->retry = volume_info->retry;
3320 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003321 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003322 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003323 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003324
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303325 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003326 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303327 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003328
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303329 cifs_fscache_get_super_cookie(tcon);
3330
Jeff Laytond00c28d2010-04-24 07:57:44 -04003331 return tcon;
3332
3333out_fail:
3334 tconInfoFree(tcon);
3335 return ERR_PTR(rc);
3336}
3337
Jeff Layton9d002df2010-10-06 19:51:11 -04003338void
3339cifs_put_tlink(struct tcon_link *tlink)
3340{
3341 if (!tlink || IS_ERR(tlink))
3342 return;
3343
3344 if (!atomic_dec_and_test(&tlink->tl_count) ||
3345 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3346 tlink->tl_time = jiffies;
3347 return;
3348 }
3349
3350 if (!IS_ERR(tlink_tcon(tlink)))
3351 cifs_put_tcon(tlink_tcon(tlink));
3352 kfree(tlink);
3353 return;
3354}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003355
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003356static int
3357compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3358{
3359 struct cifs_sb_info *old = CIFS_SB(sb);
3360 struct cifs_sb_info *new = mnt_data->cifs_sb;
3361
3362 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3363 return 0;
3364
3365 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
3366 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
3367 return 0;
3368
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003369 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003370 * We want to share sb only if we don't specify an r/wsize or
3371 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003372 */
3373 if (new->wsize && new->wsize < old->wsize)
3374 return 0;
3375
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003376 if (new->rsize && new->rsize < old->rsize)
3377 return 0;
3378
Eric W. Biederman1f682332013-02-06 01:20:20 -08003379 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003380 return 0;
3381
3382 if (old->mnt_file_mode != new->mnt_file_mode ||
3383 old->mnt_dir_mode != new->mnt_dir_mode)
3384 return 0;
3385
3386 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3387 return 0;
3388
3389 if (old->actimeo != new->actimeo)
3390 return 0;
3391
3392 return 1;
3393}
3394
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003395static int
3396match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3397{
3398 struct cifs_sb_info *old = CIFS_SB(sb);
3399 struct cifs_sb_info *new = mnt_data->cifs_sb;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003400 bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3401 bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003402
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003403 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003404 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003405 else if (!old_set && !new_set)
3406 return 1;
3407
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003408 return 0;
3409}
3410
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003411int
3412cifs_match_super(struct super_block *sb, void *data)
3413{
3414 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3415 struct smb_vol *volume_info;
3416 struct cifs_sb_info *cifs_sb;
3417 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003418 struct cifs_ses *ses;
3419 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003420 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003421 int rc = 0;
3422
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003423 spin_lock(&cifs_tcp_ses_lock);
3424 cifs_sb = CIFS_SB(sb);
3425 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3426 if (IS_ERR(tlink)) {
3427 spin_unlock(&cifs_tcp_ses_lock);
3428 return rc;
3429 }
3430 tcon = tlink_tcon(tlink);
3431 ses = tcon->ses;
3432 tcp_srv = ses->server;
3433
3434 volume_info = mnt_data->vol;
3435
Jeff Layton9fa114f2012-11-26 11:09:57 -05003436 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003437 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003438 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003439 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003440 rc = 0;
3441 goto out;
3442 }
3443
3444 rc = compare_mount_options(sb, mnt_data);
3445out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003446 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003447 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003448 return rc;
3449}
3450
Jeff Layton09e50d52008-07-23 10:11:19 -04003451#ifdef CONFIG_DEBUG_LOCK_ALLOC
3452static struct lock_class_key cifs_key[2];
3453static struct lock_class_key cifs_slock_key[2];
3454
3455static inline void
3456cifs_reclassify_socket4(struct socket *sock)
3457{
3458 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003459 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003460 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3461 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3462}
3463
3464static inline void
3465cifs_reclassify_socket6(struct socket *sock)
3466{
3467 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003468 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003469 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3470 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3471}
3472#else
3473static inline void
3474cifs_reclassify_socket4(struct socket *sock)
3475{
3476}
3477
3478static inline void
3479cifs_reclassify_socket6(struct socket *sock)
3480{
3481}
3482#endif
3483
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003485static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486{
Steve French50c2f752007-07-13 00:33:32 +00003487 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488
Steve French50c2f752007-07-13 00:33:32 +00003489 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490 /* mask a nibble at a time and encode */
3491 target[j] = 'A' + (0x0F & (source[i] >> 4));
3492 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003493 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494 }
3495
3496}
3497
Ben Greear3eb9a882010-09-01 17:06:02 -07003498static int
3499bind_socket(struct TCP_Server_Info *server)
3500{
3501 int rc = 0;
3502 if (server->srcaddr.ss_family != AF_UNSPEC) {
3503 /* Bind to the specified local IP address */
3504 struct socket *socket = server->ssocket;
3505 rc = socket->ops->bind(socket,
3506 (struct sockaddr *) &server->srcaddr,
3507 sizeof(server->srcaddr));
3508 if (rc < 0) {
3509 struct sockaddr_in *saddr4;
3510 struct sockaddr_in6 *saddr6;
3511 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3512 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3513 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05003514 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3515 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003516 else
Joe Perchesf96637b2013-05-04 22:12:25 -05003517 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3518 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003519 }
3520 }
3521 return rc;
3522}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523
3524static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003525ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526{
3527 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003528 /*
3529 * some servers require RFC1001 sessinit before sending
3530 * negprot - BB check reconnection in case where second
3531 * sessinit is sent but no second negprot
3532 */
3533 struct rfc1002_session_packet *ses_init_buf;
3534 struct smb_hdr *smb_buf;
3535 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3536 GFP_KERNEL);
3537 if (ses_init_buf) {
3538 ses_init_buf->trailer.session_req.called_len = 32;
3539
Colin Ian King997152f2016-01-25 16:25:54 +00003540 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003541 rfc1002mangle(ses_init_buf->trailer.
3542 session_req.called_name,
3543 server->server_RFC1001_name,
3544 RFC1001_NAME_LEN_WITH_NULL);
3545 else
3546 rfc1002mangle(ses_init_buf->trailer.
3547 session_req.called_name,
3548 DEFAULT_CIFS_CALLED_NAME,
3549 RFC1001_NAME_LEN_WITH_NULL);
3550
3551 ses_init_buf->trailer.session_req.calling_len = 32;
3552
3553 /*
3554 * calling name ends in null (byte 16) from old smb
3555 * convention.
3556 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003557 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003558 rfc1002mangle(ses_init_buf->trailer.
3559 session_req.calling_name,
3560 server->workstation_RFC1001_name,
3561 RFC1001_NAME_LEN_WITH_NULL);
3562 else
3563 rfc1002mangle(ses_init_buf->trailer.
3564 session_req.calling_name,
3565 "LINUX_CIFS_CLNT",
3566 RFC1001_NAME_LEN_WITH_NULL);
3567
3568 ses_init_buf->trailer.session_req.scope1 = 0;
3569 ses_init_buf->trailer.session_req.scope2 = 0;
3570 smb_buf = (struct smb_hdr *)ses_init_buf;
3571
3572 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003573 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003574 rc = smb_send(server, smb_buf, 0x44);
3575 kfree(ses_init_buf);
3576 /*
3577 * RFC1001 layer in at least one server
3578 * requires very short break before negprot
3579 * presumably because not expecting negprot
3580 * to follow so fast. This is a simple
3581 * solution that works without
3582 * complicating the code and causes no
3583 * significant slowing down on mount
3584 * for everyone else
3585 */
3586 usleep_range(1000, 2000);
3587 }
3588 /*
3589 * else the negprot may still work without this
3590 * even though malloc failed
3591 */
3592
3593 return rc;
3594}
3595
3596static int
3597generic_ip_connect(struct TCP_Server_Info *server)
3598{
3599 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003600 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003601 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003602 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003603 struct sockaddr *saddr;
3604
3605 saddr = (struct sockaddr *) &server->dstaddr;
3606
3607 if (server->dstaddr.ss_family == AF_INET6) {
3608 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3609 slen = sizeof(struct sockaddr_in6);
3610 sfamily = AF_INET6;
3611 } else {
3612 sport = ((struct sockaddr_in *) saddr)->sin_port;
3613 slen = sizeof(struct sockaddr_in);
3614 sfamily = AF_INET;
3615 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003617 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003618 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3619 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003621 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003622 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003625
3626 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003627 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003628 server->ssocket = socket;
3629 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003630 if (sfamily == AF_INET6)
3631 cifs_reclassify_socket6(socket);
3632 else
3633 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 }
3635
Ben Greear3eb9a882010-09-01 17:06:02 -07003636 rc = bind_socket(server);
3637 if (rc < 0)
3638 return rc;
3639
Jeff Laytond5c56052008-12-01 18:42:33 -05003640 /*
3641 * Eventually check for other socket options to change from
3642 * the default. sock_setsockopt not used because it expects
3643 * user space buffer
3644 */
3645 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003646 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003647
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003648 /* make the bufsizes depend on wsize/rsize and max requests */
3649 if (server->noautotune) {
3650 if (socket->sk->sk_sndbuf < (200 * 1024))
3651 socket->sk->sk_sndbuf = 200 * 1024;
3652 if (socket->sk->sk_rcvbuf < (140 * 1024))
3653 socket->sk->sk_rcvbuf = 140 * 1024;
3654 }
3655
Steve French6a5fa2362010-01-01 01:28:43 +00003656 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003657 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003658 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3659 (char *)&val, sizeof(val));
3660 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003661 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3662 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003663 }
3664
Joe Perchesf96637b2013-05-04 22:12:25 -05003665 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003666 socket->sk->sk_sndbuf,
3667 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3668
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003669 rc = socket->ops->connect(socket, saddr, slen, 0);
3670 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003671 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003672 sock_release(socket);
3673 server->ssocket = NULL;
3674 return rc;
3675 }
3676
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003677 if (sport == htons(RFC1001_PORT))
3678 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003679
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 return rc;
3681}
3682
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003683static int
3684ip_connect(struct TCP_Server_Info *server)
3685{
Steve French6da97912011-03-13 18:55:55 +00003686 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003687 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3688 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3689
3690 if (server->dstaddr.ss_family == AF_INET6)
3691 sport = &addr6->sin6_port;
3692 else
3693 sport = &addr->sin_port;
3694
3695 if (*sport == 0) {
3696 int rc;
3697
3698 /* try with 445 port at first */
3699 *sport = htons(CIFS_PORT);
3700
3701 rc = generic_ip_connect(server);
3702 if (rc >= 0)
3703 return rc;
3704
3705 /* if it failed, try with 139 port */
3706 *sport = htons(RFC1001_PORT);
3707 }
3708
3709 return generic_ip_connect(server);
3710}
3711
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003712void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003713 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003714{
3715 /* if we are reconnecting then should we check to see if
3716 * any requested capabilities changed locally e.g. via
3717 * remount but we can not do much about it here
3718 * if they have (even if we could detect it by the following)
3719 * Perhaps we could add a backpointer to array of sb from tcon
3720 * or if we change to make all sb to same share the same
3721 * sb as NFS - then we only have one backpointer to sb.
3722 * What if we wanted to mount the server share twice once with
3723 * and once without posixacls or posix paths? */
3724 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003725
Steve Frenchc18c8422007-07-18 23:21:09 +00003726 if (vol_info && vol_info->no_linux_ext) {
3727 tcon->fsUnixInfo.Capability = 0;
3728 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003729 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003730 return;
3731 } else if (vol_info)
3732 tcon->unix_ext = 1; /* Unix Extensions supported */
3733
3734 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003735 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003736 return;
3737 }
Steve French50c2f752007-07-13 00:33:32 +00003738
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003739 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003740 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003741 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003742 /* check for reconnect case in which we do not
3743 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003744 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003745 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003746 originally at mount time */
3747 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3748 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003749 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3750 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003751 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003752 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003753 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003754 cifs_dbg(VFS, "possible reconnect error\n");
3755 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003756 }
Steve French8af18972007-02-14 04:42:51 +00003757 }
Steve French50c2f752007-07-13 00:33:32 +00003758
Steve French6848b732011-05-26 18:38:54 +00003759 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003760 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003761
Steve French8af18972007-02-14 04:42:51 +00003762 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003763 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003764 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003765 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003766 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003767 if (cifs_sb)
3768 cifs_sb->mnt_cifs_flags |=
3769 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003770 }
3771
Steve French75865f8c2007-06-24 18:30:48 +00003772 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003773 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003774 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003775 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003776 if (cifs_sb)
3777 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003778 CIFS_MOUNT_POSIX_PATHS;
3779 }
Steve French50c2f752007-07-13 00:33:32 +00003780
Joe Perchesf96637b2013-05-04 22:12:25 -05003781 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003782#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003783 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003784 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003785 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003786 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003787 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003788 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003789 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003790 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003791 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003792 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003793 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003794 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003795 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003796 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003797 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003798 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003799 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003800 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003801#endif /* CIFS_DEBUG2 */
3802 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003803 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003804 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003805 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003806 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 +00003807
Steve French8af18972007-02-14 04:42:51 +00003808 }
3809 }
3810}
3811
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003812int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003813 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003814{
Jeff Layton2de970f2010-10-06 19:51:12 -04003815 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3816
Al Viro2ced6f62011-06-17 09:20:04 -04003817 spin_lock_init(&cifs_sb->tlink_tree_lock);
3818 cifs_sb->tlink_tree = RB_ROOT;
3819
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003820 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003821 * Temporarily set r/wsize for matching superblock. If we end up using
3822 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003823 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003824 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003825 cifs_sb->wsize = pvolume_info->wsize;
3826
Steve French3b795212008-11-13 19:45:32 +00003827 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3828 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3829 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3830 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003831 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3832 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003833
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303834 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003835 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303836
Aurelien Aptel83930722018-09-20 18:10:25 -07003837 if (pvolume_info->nodfs)
3838 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00003839 if (pvolume_info->noperm)
3840 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3841 if (pvolume_info->setuids)
3842 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05003843 if (pvolume_info->setuidfromacl)
3844 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00003845 if (pvolume_info->server_ino)
3846 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3847 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003848 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3849 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003850 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3851 if (pvolume_info->no_xattr)
3852 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3853 if (pvolume_info->sfu_emul)
3854 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3855 if (pvolume_info->nobrl)
3856 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05003857 if (pvolume_info->nohandlecache)
3858 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00003859 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003860 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003861 if (pvolume_info->mand_lock)
3862 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003863 if (pvolume_info->rwpidforward)
3864 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003865 if (pvolume_info->cifs_acl)
3866 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003867 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003868 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003869 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3870 }
3871 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003872 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003873 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3874 }
Steve French3b795212008-11-13 19:45:32 +00003875 if (pvolume_info->override_uid)
3876 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3877 if (pvolume_info->override_gid)
3878 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3879 if (pvolume_info->dynperm)
3880 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303881 if (pvolume_info->fsc)
3882 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003883 if (pvolume_info->multiuser)
3884 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3885 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003886 if (pvolume_info->strict_io)
3887 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003888 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003889 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003890 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3891 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003892 if (pvolume_info->mfsymlinks) {
3893 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003894 /*
3895 * Our SFU ("Services for Unix" emulation does not allow
3896 * creating symlinks but does allow reading existing SFU
3897 * symlinks (it does allow both creating and reading SFU
3898 * style mknod and FIFOs though). When "mfsymlinks" and
3899 * "sfu" are both enabled at the same time, it allows
3900 * reading both types of symlinks, but will only create
3901 * them with mfsymlinks format. This allows better
3902 * Apple compatibility (probably better for Samba too)
3903 * while still recognizing old Windows style symlinks.
3904 */
3905 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003906 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003907 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003908 }
Steve French3b795212008-11-13 19:45:32 +00003909
3910 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003911 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003912
3913 if (pvolume_info->prepath) {
3914 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
3915 if (cifs_sb->prepath == NULL)
3916 return -ENOMEM;
3917 }
3918
3919 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003920}
3921
Paulo Alcantara56c762e2018-11-14 13:03:14 -02003922void
3923cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003924{
Sean Finneyb9468452011-04-11 13:19:32 +00003925 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003926 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003927 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003928 kfree(volume_info->domainname);
3929 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003930 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003931}
3932
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003933void
3934cifs_cleanup_volume_info(struct smb_vol *volume_info)
3935{
3936 if (!volume_info)
3937 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02003938 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003939 kfree(volume_info);
3940}
3941
Paulo Alcantara56c762e2018-11-14 13:03:14 -02003942/* Release all succeed connections */
3943static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
3944 unsigned int xid,
3945 struct TCP_Server_Info *server,
3946 struct cifs_ses *ses, struct cifs_tcon *tcon)
3947{
3948 int rc = 0;
3949
3950 if (tcon)
3951 cifs_put_tcon(tcon);
3952 else if (ses)
3953 cifs_put_smb_ses(ses);
3954 else if (server)
3955 cifs_put_tcp_session(server, 0);
3956 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
3957 free_xid(xid);
3958}
3959
3960/* Get connections for tcp, ses and tcon */
3961static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
3962 unsigned int *xid,
3963 struct TCP_Server_Info **nserver,
3964 struct cifs_ses **nses, struct cifs_tcon **ntcon)
3965{
3966 int rc = 0;
3967 struct TCP_Server_Info *server;
3968 struct cifs_ses *ses;
3969 struct cifs_tcon *tcon;
3970
3971 *nserver = NULL;
3972 *nses = NULL;
3973 *ntcon = NULL;
3974
3975 *xid = get_xid();
3976
3977 /* get a reference to a tcp session */
3978 server = cifs_get_tcp_session(vol);
3979 if (IS_ERR(server)) {
3980 rc = PTR_ERR(server);
3981 return rc;
3982 }
3983
3984 *nserver = server;
3985
3986 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
3987 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
3988 else
3989 server->max_credits = vol->max_credits;
3990
3991 /* get a reference to a SMB session */
3992 ses = cifs_get_smb_ses(server, vol);
3993 if (IS_ERR(ses)) {
3994 rc = PTR_ERR(ses);
3995 return rc;
3996 }
3997
3998 *nses = ses;
3999
4000 if ((vol->persistent == true) && (!(ses->server->capabilities &
4001 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
4002 cifs_dbg(VFS, "persistent handles not supported by server\n");
4003 return -EOPNOTSUPP;
4004 }
4005
4006 /* search for existing tcon to this server share */
4007 tcon = cifs_get_tcon(ses, vol);
4008 if (IS_ERR(tcon)) {
4009 rc = PTR_ERR(tcon);
4010 return rc;
4011 }
4012
4013 *ntcon = tcon;
4014
4015 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4016 if (tcon->posix_extensions)
4017 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4018
4019 /* tell server which Unix caps we support */
4020 if (cap_unix(tcon->ses)) {
4021 /*
4022 * reset of caps checks mount to see if unix extensions disabled
4023 * for just this mount.
4024 */
4025 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4026 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4027 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4028 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4029 return -EACCES;
4030 } else
4031 tcon->unix_ext = 0; /* server does not support them */
4032
4033 /* do not care if a following call succeed - informational */
4034 if (!tcon->pipe && server->ops->qfs_tcon)
4035 server->ops->qfs_tcon(*xid, tcon);
4036
4037 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4038 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4039
4040 return 0;
4041}
4042
4043static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4044 struct cifs_tcon *tcon)
4045{
4046 struct tcon_link *tlink;
4047
4048 /* hang the tcon off of the superblock */
4049 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4050 if (tlink == NULL)
4051 return -ENOMEM;
4052
4053 tlink->tl_uid = ses->linux_uid;
4054 tlink->tl_tcon = tcon;
4055 tlink->tl_time = jiffies;
4056 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4057 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4058
4059 cifs_sb->master_tlink = tlink;
4060 spin_lock(&cifs_sb->tlink_tree_lock);
4061 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4062 spin_unlock(&cifs_sb->tlink_tree_lock);
4063
4064 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4065 TLINK_IDLE_EXPIRE);
4066 return 0;
4067}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004068
Steve French2d6d5892009-04-09 00:36:44 +00004069#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004070/*
4071 * cifs_build_path_to_root returns full path to root when we do not have an
4072 * exiting connection (tcon)
4073 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004074static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004075build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004076 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004077{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004078 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004079 unsigned int pplen = useppath && vol->prepath ?
4080 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004081 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004082
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004083 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004084 if (full_path == NULL)
4085 return ERR_PTR(-ENOMEM);
4086
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004087 strncpy(full_path, vol->UNC, unc_len);
4088 pos = full_path + unc_len;
4089
4090 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004091 *pos = CIFS_DIR_SEP(cifs_sb);
4092 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004093 pos += pplen;
4094 }
4095
4096 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004097 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004098 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004099 return full_path;
4100}
Sean Finneydd613942011-04-11 13:19:30 +00004101
Paulo Alcantara1c780222018-11-14 16:24:03 -02004102/**
4103 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4104 *
Sean Finneydd613942011-04-11 13:19:30 +00004105 *
Sean Finney046462a2011-04-11 13:19:33 +00004106 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4107 * to a string containing updated options for the submount. Otherwise it
4108 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004109 *
4110 * Returns the rc from get_dfs_path to the caller, which can be used to
4111 * determine whether there were referrals.
4112 */
4113static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004114expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004115 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00004116 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00004117{
4118 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004119 struct dfs_info3_param referral = {0};
Sean Finneydd613942011-04-11 13:19:30 +00004120 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4121
Aurelien Aptel83930722018-09-20 18:10:25 -07004122 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4123 return -EREMOTE;
4124
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004125 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004126 if (IS_ERR(full_path))
4127 return PTR_ERR(full_path);
4128
4129 /* For DFS paths, skip the first '\' of the UNC */
4130 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4131
Paulo Alcantara1c780222018-11-14 16:24:03 -02004132 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4133 ref_path, &referral, NULL);
4134 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004135 char *fake_devname = NULL;
4136
4137 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004138 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004139 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004140 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004141
Sean Finneydd613942011-04-11 13:19:30 +00004142 if (IS_ERR(mdata)) {
4143 rc = PTR_ERR(mdata);
4144 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004145 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004146 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004147 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004148 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004149 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004150 kfree(fake_devname);
4151 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004152 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004153 }
4154 kfree(full_path);
4155 return rc;
4156}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004157
4158static inline int get_next_dfs_tgt(const char *path,
4159 struct dfs_cache_tgt_list *tgt_list,
4160 struct dfs_cache_tgt_iterator **tgt_it)
4161{
4162 if (!*tgt_it)
4163 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4164 else
4165 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4166 return !*tgt_it ? -EHOSTDOWN : 0;
4167}
4168
4169static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4170 struct smb_vol *fake_vol, struct smb_vol *vol)
4171{
4172 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4173 int len = strlen(tgt) + 2;
4174 char *new_unc;
4175
4176 new_unc = kmalloc(len, GFP_KERNEL);
4177 if (!new_unc)
4178 return -ENOMEM;
4179 snprintf(new_unc, len, "\\%s", tgt);
4180
4181 kfree(vol->UNC);
4182 vol->UNC = new_unc;
4183
4184 if (fake_vol->prepath) {
4185 kfree(vol->prepath);
4186 vol->prepath = fake_vol->prepath;
4187 fake_vol->prepath = NULL;
4188 }
4189 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4190
4191 return 0;
4192}
4193
4194static int setup_dfs_tgt_conn(const char *path,
4195 const struct dfs_cache_tgt_iterator *tgt_it,
4196 struct cifs_sb_info *cifs_sb,
4197 struct smb_vol *vol,
4198 unsigned int *xid,
4199 struct TCP_Server_Info **server,
4200 struct cifs_ses **ses,
4201 struct cifs_tcon **tcon)
4202{
4203 int rc;
4204 struct dfs_info3_param ref = {0};
4205 char *mdata = NULL, *fake_devname = NULL;
4206 struct smb_vol fake_vol = {0};
4207
4208 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4209
4210 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4211 if (rc)
4212 return rc;
4213
4214 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4215 &fake_devname);
4216 free_dfs_info_param(&ref);
4217
4218 if (IS_ERR(mdata)) {
4219 rc = PTR_ERR(mdata);
4220 mdata = NULL;
4221 } else {
4222 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4223 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4224 false);
4225 }
4226 kfree(mdata);
4227 kfree(fake_devname);
4228
4229 if (!rc) {
4230 /*
4231 * We use a 'fake_vol' here because we need pass it down to the
4232 * mount_{get,put} functions to test connection against new DFS
4233 * targets.
4234 */
4235 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4236 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4237 tcon);
4238 if (!rc) {
4239 /*
4240 * We were able to connect to new target server.
4241 * Update current volume info with new target server.
4242 */
4243 rc = update_vol_info(tgt_it, &fake_vol, vol);
4244 }
4245 }
4246 cifs_cleanup_volume_info_contents(&fake_vol);
4247 return rc;
4248}
4249
4250static int mount_do_dfs_failover(const char *path,
4251 struct cifs_sb_info *cifs_sb,
4252 struct smb_vol *vol,
4253 struct cifs_ses *root_ses,
4254 unsigned int *xid,
4255 struct TCP_Server_Info **server,
4256 struct cifs_ses **ses,
4257 struct cifs_tcon **tcon)
4258{
4259 int rc;
4260 struct dfs_cache_tgt_list tgt_list;
4261 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4262
4263 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4264 return -EOPNOTSUPP;
4265
4266 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4267 if (rc)
4268 return rc;
4269
4270 for (;;) {
4271 /* Get next DFS target server - if any */
4272 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4273 if (rc)
4274 break;
4275 /* Connect to next DFS target */
4276 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4277 ses, tcon);
4278 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4279 break;
4280 }
4281 if (!rc) {
4282 /*
4283 * Update DFS target hint in DFS referral cache with the target
4284 * server we successfully reconnected to.
4285 */
4286 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4287 cifs_sb->local_nls,
4288 cifs_remap(cifs_sb), path,
4289 tgt_it);
4290 }
4291 dfs_cache_free_tgts(&tgt_list);
4292 return rc;
4293}
Steve French2d6d5892009-04-09 00:36:44 +00004294#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004295
Jeff Layton04db79b2011-07-06 08:10:38 -04004296static int
4297cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004298 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004300 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004301
Steve Frenchc7c137b2018-06-06 17:59:29 -05004302 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004303 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304
Jeff Layton7586b762008-12-01 18:41:49 -05004305 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004306 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004307 kfree(volume_info->username);
4308 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004309 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004311 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004313 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004314 /* In userspace mount helper we can get user name from alternate
4315 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004316 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 }
4318
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004320 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004321 /* load_nls_default cannot return null */
4322 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004324 volume_info->local_nls = load_nls(volume_info->iocharset);
4325 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004326 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004327 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004328 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 }
4330 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004331
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004332 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004333}
4334
4335struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004336cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004337{
4338 int rc;
4339 struct smb_vol *volume_info;
4340
Jeff Layton6ee95422012-11-26 11:09:57 -05004341 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004342 if (!volume_info)
4343 return ERR_PTR(-ENOMEM);
4344
Steve Frenchc7c137b2018-06-06 17:59:29 -05004345 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004346 if (rc) {
4347 cifs_cleanup_volume_info(volume_info);
4348 volume_info = ERR_PTR(rc);
4349 }
4350
4351 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004352}
4353
Aurelien Aptela6b50582016-05-25 19:59:09 +02004354static int
4355cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4356 unsigned int xid,
4357 struct cifs_tcon *tcon,
4358 struct cifs_sb_info *cifs_sb,
4359 char *full_path)
4360{
4361 int rc;
4362 char *s;
4363 char sep, tmp;
4364
4365 sep = CIFS_DIR_SEP(cifs_sb);
4366 s = full_path;
4367
4368 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4369 while (rc == 0) {
4370 /* skip separators */
4371 while (*s == sep)
4372 s++;
4373 if (!*s)
4374 break;
4375 /* next separator */
4376 while (*s && *s != sep)
4377 s++;
4378
4379 /*
4380 * temporarily null-terminate the path at the end of
4381 * the current component
4382 */
4383 tmp = *s;
4384 *s = 0;
4385 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4386 full_path);
4387 *s = tmp;
4388 }
4389 return rc;
4390}
4391
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004392/*
4393 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4394 * otherwise 0.
4395 */
4396static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4397 const unsigned int xid,
4398 struct TCP_Server_Info *server,
4399 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004400{
Jeff Layton1daaae82012-03-21 06:30:40 -04004401 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004402 char *full_path;
4403
4404 if (!server->ops->is_path_accessible)
4405 return -EOPNOTSUPP;
4406
4407 /*
4408 * cifs_build_path_to_root works only when we have a valid tcon
4409 */
4410 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4411 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4412 if (full_path == NULL)
4413 return -ENOMEM;
4414
4415 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4416
4417 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4418 full_path);
4419 if (rc != 0 && rc != -EREMOTE) {
4420 kfree(full_path);
4421 return rc;
4422 }
4423
4424 if (rc != -EREMOTE) {
4425 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
4426 cifs_sb,
4427 full_path);
4428 if (rc != 0) {
4429 cifs_dbg(VFS, "cannot query dirs between root and final path, "
4430 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4431 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4432 rc = 0;
4433 }
4434 }
4435
4436 kfree(full_path);
4437 return rc;
4438}
4439
4440#ifdef CONFIG_CIFS_DFS_UPCALL
4441int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4442{
4443 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004444 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004445 struct cifs_ses *ses;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004446 struct cifs_tcon *root_tcon = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004447 struct cifs_tcon *tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004448 struct TCP_Server_Info *server;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004449 char *root_path = NULL, *full_path = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004450 char *old_mountdata;
4451 int count;
Al Virodd854462011-06-17 08:24:42 -04004452
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004453 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4454 if (!rc && tcon) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004455 /* If not a standalone DFS root, then check if path is remote */
4456 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4457 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4458 NULL);
4459 if (rc) {
4460 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4461 if (!rc)
4462 goto out;
4463 if (rc != -EREMOTE)
4464 goto error;
4465 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004466 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004467 /*
4468 * If first DFS target server went offline and we failed to connect it,
4469 * server and ses pointers are NULL at this point, though we still have
4470 * chance to get a cached DFS referral in expand_dfs_referral() and
4471 * retry next target available in it.
4472 *
4473 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4474 * performed against DFS path and *no* requests will be sent to server
4475 * for any new DFS referrals. Hence it's safe to skip checking whether
4476 * server or ses ptr is NULL.
4477 */
4478 if (rc == -EACCES || rc == -EOPNOTSUPP)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004479 goto error;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004480
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004481 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4482 if (IS_ERR(root_path)) {
4483 rc = PTR_ERR(root_path);
4484 root_path = NULL;
4485 goto error;
4486 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004488 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4489 if (IS_ERR(full_path)) {
4490 rc = PTR_ERR(full_path);
4491 full_path = NULL;
4492 goto error;
4493 }
Sean Finneyc1508ca2011-04-11 13:19:31 +00004494 /*
4495 * Perform an unconditional check for whether there are DFS
4496 * referrals for this path without prefix, to provide support
4497 * for DFS referrals from w2k8 servers which don't seem to respond
4498 * with PATH_NOT_COVERED to requests that include the prefix.
4499 * Chase the referral if found, otherwise continue normally.
4500 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004501 old_mountdata = cifs_sb->mountdata;
4502 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004503
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004504 if (cifs_sb->mountdata == NULL) {
4505 rc = -ENOENT;
4506 goto error;
4507 }
4508
4509 if (cifs_sb->mountdata != old_mountdata) {
4510 /* If we were redirected, reconnect to new target server */
4511 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4512 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4513 }
4514 if (rc) {
4515 if (rc == -EACCES || rc == -EOPNOTSUPP)
4516 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004517 /* Perform DFS failover to any other DFS targets */
4518 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4519 &xid, &server, &ses, &tcon);
4520 if (rc)
4521 goto error;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004522 }
4523
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004524 kfree(root_path);
4525 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4526 if (IS_ERR(root_path)) {
4527 rc = PTR_ERR(root_path);
4528 root_path = NULL;
4529 goto error;
4530 }
4531 /* Cache out resolved root server */
4532 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4533 root_path + 1, NULL, NULL);
4534 /*
4535 * Save root tcon for additional DFS requests to update or create a new
4536 * DFS cache entry, or even perform DFS failover.
4537 */
4538 spin_lock(&cifs_tcp_ses_lock);
4539 tcon->tc_count++;
4540 tcon->dfs_path = root_path;
4541 root_path = NULL;
4542 tcon->remap = cifs_remap(cifs_sb);
4543 spin_unlock(&cifs_tcp_ses_lock);
4544
4545 root_tcon = tcon;
4546
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004547 for (count = 1; ;) {
4548 if (!rc && tcon) {
4549 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4550 if (!rc || rc != -EREMOTE)
4551 break;
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004552 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004553 /*
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004554 * BB: when we implement proper loop detection,
4555 * we will remove this check. But now we need it
4556 * to prevent an indefinite loop if 'DFS tree' is
4557 * misconfigured (i.e. has loops).
Steve French6d3ea7e2012-11-28 22:34:41 -06004558 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004559 if (count++ > MAX_NESTED_LINKS) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004560 rc = -ELOOP;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004561 break;
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004562 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004563
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004564 kfree(full_path);
4565 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4566 if (IS_ERR(full_path)) {
4567 rc = PTR_ERR(full_path);
4568 full_path = NULL;
4569 break;
4570 }
4571
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004572 old_mountdata = cifs_sb->mountdata;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004573 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004574 true);
4575 if (rc)
4576 break;
Jeff Layton7b91e262009-07-23 15:22:30 -04004577
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004578 if (cifs_sb->mountdata != old_mountdata) {
4579 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4580 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4581 &tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004582 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004583 if (rc) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004584 if (rc == -EACCES || rc == -EOPNOTSUPP)
4585 break;
4586 /* Perform DFS failover to any other DFS targets */
4587 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4588 root_tcon->ses, &xid,
4589 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004590 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4591 !ses)
4592 goto error;
4593 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004594 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004595 cifs_put_tcon(root_tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004596
Jeff Layton9d002df2010-10-06 19:51:11 -04004597 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004598 goto error;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004599
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004600 spin_lock(&cifs_tcp_ses_lock);
4601 if (!tcon->dfs_path) {
4602 /* Save full path in new tcon to do failover when reconnecting tcons */
4603 tcon->dfs_path = full_path;
4604 full_path = NULL;
4605 tcon->remap = cifs_remap(cifs_sb);
4606 }
4607 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
YueHaibing2f0a6172018-12-18 01:34:39 +00004608 strlen(tcon->dfs_path),
4609 GFP_ATOMIC);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004610 if (!cifs_sb->origin_fullpath) {
4611 spin_unlock(&cifs_tcp_ses_lock);
4612 rc = -ENOMEM;
4613 goto error;
4614 }
4615 spin_unlock(&cifs_tcp_ses_lock);
4616
Paulo Alcantarae511d312018-11-14 17:16:44 -02004617 rc = dfs_cache_add_vol(vol, cifs_sb->origin_fullpath);
4618 if (rc) {
4619 kfree(cifs_sb->origin_fullpath);
4620 goto error;
4621 }
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004622 /*
4623 * After reconnecting to a different server, unique ids won't
4624 * match anymore, so we disable serverino. This prevents
4625 * dentry revalidation to think the dentry are stale (ESTALE).
4626 */
4627 cifs_autodisable_serverino(cifs_sb);
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004628out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004629 free_xid(xid);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004630 return mount_setup_tlink(cifs_sb, ses, tcon);
4631
4632error:
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004633 kfree(full_path);
4634 kfree(root_path);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004635 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636 return rc;
4637}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004638#else
4639int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4640{
4641 int rc = 0;
4642 unsigned int xid;
4643 struct cifs_ses *ses;
4644 struct cifs_tcon *tcon;
4645 struct TCP_Server_Info *server;
4646
4647 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4648 if (rc)
4649 goto error;
4650
4651 if (tcon) {
4652 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4653 if (rc == -EREMOTE)
4654 rc = -EOPNOTSUPP;
4655 if (rc)
4656 goto error;
4657 }
4658
4659 free_xid(xid);
4660
4661 return mount_setup_tlink(cifs_sb, ses, tcon);
4662
4663error:
4664 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4665 return rc;
4666}
4667#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004668
Jeff Layton8d1bca32011-06-11 21:17:10 -04004669/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01004670 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04004671 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004672int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04004673CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00004674 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004675 const struct nls_table *nls_codepage)
4676{
4677 struct smb_hdr *smb_buffer;
4678 struct smb_hdr *smb_buffer_response;
4679 TCONX_REQ *pSMB;
4680 TCONX_RSP *pSMBr;
4681 unsigned char *bcc_ptr;
4682 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05004683 int length;
4684 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685
4686 if (ses == NULL)
4687 return -EIO;
4688
4689 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00004690 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00004692
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693 smb_buffer_response = smb_buffer;
4694
4695 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
4696 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07004697
Pavel Shilovsky88257362012-05-23 14:01:59 +04004698 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699 smb_buffer->Uid = ses->Suid;
4700 pSMB = (TCONX_REQ *) smb_buffer;
4701 pSMBr = (TCONX_RSP *) smb_buffer_response;
4702
4703 pSMB->AndXCommand = 0xFF;
4704 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004705 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01004706 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08004707 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00004708 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08004709 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00004710 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08004711 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004712 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08004713 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
4714 specified as required (when that support is added to
4715 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00004716 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08004717 by Samba (not sure whether other servers allow
4718 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00004719#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04004720 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05004721 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05004722 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00004723 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05004724 SECMODE_PW_ENCRYPT ? true : false,
4725 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00004726 else
4727#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06004728 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05004729 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05004730 if (rc) {
4731 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
4732 __func__, rc);
4733 cifs_buf_release(smb_buffer);
4734 return rc;
4735 }
Steve Frencheeac8042006-01-13 21:34:58 -08004736
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004737 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004738 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00004739 /* must align unicode strings */
4740 *bcc_ptr = 0; /* null byte password */
4741 bcc_ptr++;
4742 }
Steve Frencheeac8042006-01-13 21:34:58 -08004743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004744
Jeff Layton38d77c52013-05-26 07:01:00 -04004745 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4747
4748 if (ses->capabilities & CAP_STATUS32) {
4749 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
4750 }
4751 if (ses->capabilities & CAP_DFS) {
4752 smb_buffer->Flags2 |= SMBFLG2_DFS;
4753 }
4754 if (ses->capabilities & CAP_UNICODE) {
4755 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
4756 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06004757 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004758 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004759 (/* server len*/ + 256 /* share len */), nls_codepage);
4760 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004761 bcc_ptr += 2; /* skip trailing null */
4762 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763 strcpy(bcc_ptr, tree);
4764 bcc_ptr += strlen(tree) + 1;
4765 }
4766 strcpy(bcc_ptr, "?????");
4767 bcc_ptr += strlen("?????");
4768 bcc_ptr += 1;
4769 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004770 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4771 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772 pSMB->ByteCount = cpu_to_le16(count);
4773
Steve French133672e2007-11-13 22:41:37 +00004774 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004775 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01004778 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004779 bool is_unicode;
4780
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004782 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783 tcon->tid = smb_buffer_response->Tid;
4784 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004785 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004786 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004787 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4788 is_unicode = true;
4789 else
4790 is_unicode = false;
4791
Jeff Laytoncc20c032009-04-30 07:16:21 -04004792
Steve French50c2f752007-07-13 00:33:32 +00004793 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004794 if (length == 3) {
4795 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4796 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004797 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01004798 tcon->ipc = true;
4799 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00004800 }
4801 } else if (length == 2) {
4802 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4803 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05004804 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004805 }
4806 }
Steve French50c2f752007-07-13 00:33:32 +00004807 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004808 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05004809 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04004810
4811 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004812 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004813 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004814 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004815 nls_codepage);
4816
Joe Perchesf96637b2013-05-04 22:12:25 -05004817 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004818
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004819 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004820 (smb_buffer_response->WordCount == 7))
4821 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004822 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4823 else
4824 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05004825 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826 }
4827
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004828 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829 return rc;
4830}
4831
Al Viro2e32cf52013-10-03 12:53:37 -04004832static void delayed_free(struct rcu_head *p)
4833{
4834 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
4835 unload_nls(sbi->local_nls);
4836 kfree(sbi);
4837}
4838
Al Viro2a9b9952011-06-17 09:27:16 -04004839void
4840cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841{
Jeff Laytonb647c352010-10-28 11:16:44 -04004842 struct rb_root *root = &cifs_sb->tlink_tree;
4843 struct rb_node *node;
4844 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845
Jeff Layton2de970f2010-10-06 19:51:12 -04004846 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4847
Jeff Laytonb647c352010-10-28 11:16:44 -04004848 spin_lock(&cifs_sb->tlink_tree_lock);
4849 while ((node = rb_first(root))) {
4850 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4851 cifs_get_tlink(tlink);
4852 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4853 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004854
Jeff Laytonb647c352010-10-28 11:16:44 -04004855 spin_unlock(&cifs_sb->tlink_tree_lock);
4856 cifs_put_tlink(tlink);
4857 spin_lock(&cifs_sb->tlink_tree_lock);
4858 }
4859 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004860
Al Virod757d712011-06-17 09:42:43 -04004861 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02004862 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004863#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02004864 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004865 kfree(cifs_sb->origin_fullpath);
4866#endif
Al Viro2e32cf52013-10-03 12:53:37 -04004867 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00004868}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004869
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004870int
4871cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004872{
4873 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004874 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004875
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004876 if (!server->ops->need_neg || !server->ops->negotiate)
4877 return -ENOSYS;
4878
Jeff Layton198b5682010-04-24 07:57:48 -04004879 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004880 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04004881 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004882
Pavel Shilovsky45275782012-05-17 17:53:29 +04004883 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004884
4885 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04004886 if (rc == 0) {
4887 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004888 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004889 server->tcpStatus = CifsGood;
4890 else
4891 rc = -EHOSTDOWN;
4892 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893 }
Steve French26b994f2008-08-06 05:11:33 +00004894
Jeff Layton198b5682010-04-24 07:57:48 -04004895 return rc;
4896}
Steve French26b994f2008-08-06 05:11:33 +00004897
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004898int
4899cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
4900 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04004901{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004902 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04004903 struct TCP_Server_Info *server = ses->server;
4904
Jeff Layton198b5682010-04-24 07:57:48 -04004905 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004906 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004907 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00004908
Joe Perchesf96637b2013-05-04 22:12:25 -05004909 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00004910 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004911
Shu Wangf5c4ba82017-09-08 18:48:33 +08004912 if (ses->auth_key.response) {
Steve French2a182872018-03-29 12:16:34 -05004913 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
Shu Wangf5c4ba82017-09-08 18:48:33 +08004914 ses->auth_key.response);
4915 kfree(ses->auth_key.response);
4916 ses->auth_key.response = NULL;
4917 ses->auth_key.len = 0;
4918 }
4919
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004920 if (server->ops->sess_setup)
4921 rc = server->ops->sess_setup(xid, ses, nls_info);
4922
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05004923 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05004924 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004925
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926 return rc;
4927}
4928
Jeff Layton8a8798a2012-01-17 16:09:15 -05004929static int
4930cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4931{
Jeff Layton3f618222013-06-12 19:52:14 -05004932 vol->sectype = ses->sectype;
4933
4934 /* krb5 is special, since we don't need username or pw */
4935 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05004936 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05004937
4938 return cifs_set_cifscreds(vol, ses);
4939}
4940
Steve French96daf2b2011-05-27 04:34:02 +00004941static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004942cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04004943{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004944 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004945 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4946 struct cifs_ses *ses;
4947 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004948 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004949
4950 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004951 if (vol_info == NULL)
4952 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004953
Jeff Layton9d002df2010-10-06 19:51:11 -04004954 vol_info->local_nls = cifs_sb->local_nls;
4955 vol_info->linux_uid = fsuid;
4956 vol_info->cred_uid = fsuid;
4957 vol_info->UNC = master_tcon->treeName;
4958 vol_info->retry = master_tcon->retry;
4959 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05004960 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04004961 vol_info->local_lease = master_tcon->local_lease;
4962 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004963 vol_info->sectype = master_tcon->ses->sectype;
4964 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004965
Jeff Layton8a8798a2012-01-17 16:09:15 -05004966 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4967 if (rc) {
4968 tcon = ERR_PTR(rc);
4969 goto out;
4970 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004971
4972 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304973 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004974 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304975 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004976
4977 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4978 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004979 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004980 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04004981 goto out;
4982 }
4983
4984 tcon = cifs_get_tcon(ses, vol_info);
4985 if (IS_ERR(tcon)) {
4986 cifs_put_smb_ses(ses);
4987 goto out;
4988 }
4989
Steve Frenchce558b02018-05-31 19:16:54 -05004990 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4991 if (tcon->posix_extensions)
4992 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05004993
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004994 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004995 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05004996
Jeff Layton9d002df2010-10-06 19:51:11 -04004997out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004998 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01004999 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005000 kfree(vol_info);
5001
5002 return tcon;
5003}
5004
Steve French96daf2b2011-05-27 04:34:02 +00005005struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005006cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5007{
5008 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5009}
5010
Jeff Laytonb647c352010-10-28 11:16:44 -04005011/* find and return a tlink with given uid */
5012static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005013tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005014{
5015 struct rb_node *node = root->rb_node;
5016 struct tcon_link *tlink;
5017
5018 while (node) {
5019 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5020
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005021 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005022 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005023 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005024 node = node->rb_right;
5025 else
5026 return tlink;
5027 }
5028 return NULL;
5029}
5030
5031/* insert a tcon_link into the tree */
5032static void
5033tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5034{
5035 struct rb_node **new = &(root->rb_node), *parent = NULL;
5036 struct tcon_link *tlink;
5037
5038 while (*new) {
5039 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5040 parent = *new;
5041
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005042 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005043 new = &((*new)->rb_left);
5044 else
5045 new = &((*new)->rb_right);
5046 }
5047
5048 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5049 rb_insert_color(&new_tlink->tl_rbnode, root);
5050}
5051
Jeff Layton9d002df2010-10-06 19:51:11 -04005052/*
5053 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5054 * current task.
5055 *
5056 * If the superblock doesn't refer to a multiuser mount, then just return
5057 * the master tcon for the mount.
5058 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305059 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005060 * exists, then check to see if it's pending construction. If it is then wait
5061 * for construction to complete. Once it's no longer pending, check to see if
5062 * it failed and either return an error or retry construction, depending on
5063 * the timeout.
5064 *
5065 * If one doesn't exist then insert a new tcon_link struct into the tree and
5066 * try to construct a new one.
5067 */
5068struct tcon_link *
5069cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5070{
5071 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005072 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005073 struct tcon_link *tlink, *newtlink;
5074
5075 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5076 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5077
5078 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005079 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005080 if (tlink)
5081 cifs_get_tlink(tlink);
5082 spin_unlock(&cifs_sb->tlink_tree_lock);
5083
5084 if (tlink == NULL) {
5085 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5086 if (newtlink == NULL)
5087 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005088 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005089 newtlink->tl_tcon = ERR_PTR(-EACCES);
5090 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5091 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5092 cifs_get_tlink(newtlink);
5093
Jeff Layton9d002df2010-10-06 19:51:11 -04005094 spin_lock(&cifs_sb->tlink_tree_lock);
5095 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005096 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005097 if (tlink) {
5098 cifs_get_tlink(tlink);
5099 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005100 kfree(newtlink);
5101 goto wait_for_construction;
5102 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005103 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005104 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5105 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005106 } else {
5107wait_for_construction:
5108 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005109 TASK_INTERRUPTIBLE);
5110 if (ret) {
5111 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005112 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005113 }
5114
5115 /* if it's good, return it */
5116 if (!IS_ERR(tlink->tl_tcon))
5117 return tlink;
5118
5119 /* return error if we tried this already recently */
5120 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5121 cifs_put_tlink(tlink);
5122 return ERR_PTR(-EACCES);
5123 }
5124
5125 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5126 goto wait_for_construction;
5127 }
5128
5129 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5130 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5131 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5132
5133 if (IS_ERR(tlink->tl_tcon)) {
5134 cifs_put_tlink(tlink);
5135 return ERR_PTR(-EACCES);
5136 }
5137
5138 return tlink;
5139}
Jeff Layton2de970f2010-10-06 19:51:12 -04005140
5141/*
5142 * periodic workqueue job that scans tcon_tree for a superblock and closes
5143 * out tcons.
5144 */
5145static void
5146cifs_prune_tlinks(struct work_struct *work)
5147{
5148 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5149 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005150 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005151 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005152 struct rb_node *tmp;
5153 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005154
Jeff Laytonb647c352010-10-28 11:16:44 -04005155 /*
5156 * Because we drop the spinlock in the loop in order to put the tlink
5157 * it's not guarded against removal of links from the tree. The only
5158 * places that remove entries from the tree are this function and
5159 * umounts. Because this function is non-reentrant and is canceled
5160 * before umount can proceed, this is safe.
5161 */
5162 spin_lock(&cifs_sb->tlink_tree_lock);
5163 node = rb_first(root);
5164 while (node != NULL) {
5165 tmp = node;
5166 node = rb_next(tmp);
5167 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5168
5169 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5170 atomic_read(&tlink->tl_count) != 0 ||
5171 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5172 continue;
5173
5174 cifs_get_tlink(tlink);
5175 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5176 rb_erase(tmp, root);
5177
Jeff Layton2de970f2010-10-06 19:51:12 -04005178 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005179 cifs_put_tlink(tlink);
5180 spin_lock(&cifs_sb->tlink_tree_lock);
5181 }
5182 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005183
Jeff Laytonda472fc2012-03-23 14:40:53 -04005184 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005185 TLINK_IDLE_EXPIRE);
5186}