blob: da0720f41ebcbc70062bafff127bd5d932982273 [file] [log] [blame]
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001/*
2 * fs/cifs/connect.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2011
5 * 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
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
24#include <linux/sched/signal.h>
25#include <linux/list.h>
26#include <linux/wait.h>
27#include <linux/slab.h>
28#include <linux/pagemap.h>
29#include <linux/ctype.h>
30#include <linux/utsname.h>
31#include <linux/mempool.h>
32#include <linux/delay.h>
33#include <linux/completion.h>
34#include <linux/kthread.h>
35#include <linux/pagevec.h>
36#include <linux/freezer.h>
37#include <linux/namei.h>
38#include <linux/uuid.h>
39#include <linux/uaccess.h>
40#include <asm/processor.h>
41#include <linux/inet.h>
42#include <linux/module.h>
43#include <keys/user-type.h>
44#include <net/ipv6.h>
45#include <linux/parser.h>
46#include <linux/bvec.h>
47#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"
56#include "fscache.h"
57#include "smb2proto.h"
58#include "smbdirect.h"
David Brazdil0f672f62019-12-10 10:32:29 +000059#include "dns_resolve.h"
60#include "cifsfs.h"
61#ifdef CONFIG_CIFS_DFS_UPCALL
62#include "dfs_cache.h"
63#endif
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000064
65extern mempool_t *cifs_req_poolp;
66extern bool disable_legacy_dialects;
67
68/* FIXME: should these be tunable? */
69#define TLINK_ERROR_EXPIRE (1 * HZ)
70#define TLINK_IDLE_EXPIRE (600 * HZ)
71
72enum {
73 /* Mount options that take no arguments */
74 Opt_user_xattr, Opt_nouser_xattr,
75 Opt_forceuid, Opt_noforceuid,
76 Opt_forcegid, Opt_noforcegid,
David Brazdil0f672f62019-12-10 10:32:29 +000077 Opt_noblocksend, Opt_noautotune, Opt_nolease,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000078 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
79 Opt_mapposix, Opt_nomapposix,
80 Opt_mapchars, Opt_nomapchars, Opt_sfu,
81 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
82 Opt_noposixpaths, Opt_nounix, Opt_unix,
83 Opt_nocase,
84 Opt_brl, Opt_nobrl,
85 Opt_handlecache, Opt_nohandlecache,
86 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
87 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,
David Brazdil0f672f62019-12-10 10:32:29 +000094 Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000095 Opt_fsc, Opt_mfsymlinks,
96 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
97 Opt_persistent, Opt_nopersistent,
98 Opt_resilient, Opt_noresilient,
David Brazdil0f672f62019-12-10 10:32:29 +000099 Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
100 Opt_compress,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000101
102 /* Mount options which take numeric value */
103 Opt_backupuid, Opt_backupgid, Opt_uid,
104 Opt_cruid, Opt_gid, Opt_file_mode,
105 Opt_dirmode, Opt_port,
David Brazdil0f672f62019-12-10 10:32:29 +0000106 Opt_min_enc_offload,
107 Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
108 Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000109 Opt_snapshot,
110
111 /* Mount options which take string value */
112 Opt_user, Opt_pass, Opt_ip,
113 Opt_domain, Opt_srcaddr, Opt_iocharset,
114 Opt_netbiosname, Opt_servern,
115 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
116
117 /* Mount options to be ignored */
118 Opt_ignore,
119
120 /* Options which could be blank */
121 Opt_blank_pass,
122 Opt_blank_user,
123 Opt_blank_ip,
124
125 Opt_err
126};
127
128static const match_table_t cifs_mount_option_tokens = {
129
130 { Opt_user_xattr, "user_xattr" },
131 { Opt_nouser_xattr, "nouser_xattr" },
132 { Opt_forceuid, "forceuid" },
133 { Opt_noforceuid, "noforceuid" },
134 { Opt_forcegid, "forcegid" },
135 { Opt_noforcegid, "noforcegid" },
136 { Opt_noblocksend, "noblocksend" },
137 { Opt_noautotune, "noautotune" },
David Brazdil0f672f62019-12-10 10:32:29 +0000138 { Opt_nolease, "nolease" },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000139 { Opt_hard, "hard" },
140 { Opt_soft, "soft" },
141 { Opt_perm, "perm" },
142 { Opt_noperm, "noperm" },
143 { Opt_mapchars, "mapchars" }, /* SFU style */
144 { Opt_nomapchars, "nomapchars" },
145 { Opt_mapposix, "mapposix" }, /* SFM style */
146 { Opt_nomapposix, "nomapposix" },
147 { Opt_sfu, "sfu" },
148 { Opt_nosfu, "nosfu" },
149 { Opt_nodfs, "nodfs" },
150 { Opt_posixpaths, "posixpaths" },
151 { Opt_noposixpaths, "noposixpaths" },
152 { Opt_nounix, "nounix" },
153 { Opt_nounix, "nolinux" },
154 { Opt_nounix, "noposix" },
155 { Opt_unix, "unix" },
156 { Opt_unix, "linux" },
157 { Opt_unix, "posix" },
158 { Opt_nocase, "nocase" },
159 { Opt_nocase, "ignorecase" },
160 { Opt_brl, "brl" },
161 { Opt_nobrl, "nobrl" },
162 { Opt_handlecache, "handlecache" },
163 { Opt_nohandlecache, "nohandlecache" },
164 { Opt_nobrl, "nolock" },
165 { Opt_forcemandatorylock, "forcemandatorylock" },
166 { Opt_forcemandatorylock, "forcemand" },
167 { Opt_setuids, "setuids" },
168 { Opt_nosetuids, "nosetuids" },
169 { Opt_setuidfromacl, "idsfromsid" },
170 { Opt_dynperm, "dynperm" },
171 { Opt_nodynperm, "nodynperm" },
172 { Opt_nohard, "nohard" },
173 { Opt_nosoft, "nosoft" },
174 { Opt_nointr, "nointr" },
175 { Opt_intr, "intr" },
176 { Opt_nostrictsync, "nostrictsync" },
177 { Opt_strictsync, "strictsync" },
178 { Opt_serverino, "serverino" },
179 { Opt_noserverino, "noserverino" },
180 { Opt_rwpidforward, "rwpidforward" },
David Brazdil0f672f62019-12-10 10:32:29 +0000181 { Opt_modesid, "modefromsid" },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000182 { Opt_cifsacl, "cifsacl" },
183 { Opt_nocifsacl, "nocifsacl" },
184 { Opt_acl, "acl" },
185 { Opt_noacl, "noacl" },
186 { Opt_locallease, "locallease" },
187 { Opt_sign, "sign" },
David Brazdil0f672f62019-12-10 10:32:29 +0000188 { Opt_ignore_signature, "signloosely" },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000189 { Opt_seal, "seal" },
190 { Opt_noac, "noac" },
191 { Opt_fsc, "fsc" },
192 { Opt_mfsymlinks, "mfsymlinks" },
193 { Opt_multiuser, "multiuser" },
194 { Opt_sloppy, "sloppy" },
195 { Opt_nosharesock, "nosharesock" },
196 { Opt_persistent, "persistenthandles"},
197 { Opt_nopersistent, "nopersistenthandles"},
198 { Opt_resilient, "resilienthandles"},
199 { Opt_noresilient, "noresilienthandles"},
200 { Opt_domainauto, "domainauto"},
201 { Opt_rdma, "rdma"},
202
203 { Opt_backupuid, "backupuid=%s" },
204 { Opt_backupgid, "backupgid=%s" },
205 { Opt_uid, "uid=%s" },
206 { Opt_cruid, "cruid=%s" },
207 { Opt_gid, "gid=%s" },
208 { Opt_file_mode, "file_mode=%s" },
209 { Opt_dirmode, "dirmode=%s" },
210 { Opt_dirmode, "dir_mode=%s" },
211 { Opt_port, "port=%s" },
David Brazdil0f672f62019-12-10 10:32:29 +0000212 { Opt_min_enc_offload, "esize=%s" },
213 { Opt_blocksize, "bsize=%s" },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000214 { Opt_rsize, "rsize=%s" },
215 { Opt_wsize, "wsize=%s" },
216 { Opt_actimeo, "actimeo=%s" },
David Brazdil0f672f62019-12-10 10:32:29 +0000217 { Opt_handletimeout, "handletimeout=%s" },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000218 { Opt_echo_interval, "echo_interval=%s" },
219 { Opt_max_credits, "max_credits=%s" },
220 { Opt_snapshot, "snapshot=%s" },
David Brazdil0f672f62019-12-10 10:32:29 +0000221 { Opt_compress, "compress=%s" },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000222
223 { Opt_blank_user, "user=" },
224 { Opt_blank_user, "username=" },
225 { Opt_user, "user=%s" },
226 { Opt_user, "username=%s" },
227 { Opt_blank_pass, "pass=" },
228 { Opt_blank_pass, "password=" },
229 { Opt_pass, "pass=%s" },
230 { Opt_pass, "password=%s" },
231 { Opt_blank_ip, "ip=" },
232 { Opt_blank_ip, "addr=" },
233 { Opt_ip, "ip=%s" },
234 { Opt_ip, "addr=%s" },
235 { Opt_ignore, "unc=%s" },
236 { Opt_ignore, "target=%s" },
237 { Opt_ignore, "path=%s" },
238 { Opt_domain, "dom=%s" },
239 { Opt_domain, "domain=%s" },
240 { Opt_domain, "workgroup=%s" },
241 { Opt_srcaddr, "srcaddr=%s" },
242 { Opt_ignore, "prefixpath=%s" },
243 { Opt_iocharset, "iocharset=%s" },
244 { Opt_netbiosname, "netbiosname=%s" },
245 { Opt_servern, "servern=%s" },
246 { Opt_ver, "ver=%s" },
247 { Opt_vers, "vers=%s" },
248 { Opt_sec, "sec=%s" },
249 { Opt_cache, "cache=%s" },
250
251 { Opt_ignore, "cred" },
252 { Opt_ignore, "credentials" },
253 { Opt_ignore, "cred=%s" },
254 { Opt_ignore, "credentials=%s" },
255 { Opt_ignore, "guest" },
256 { Opt_ignore, "rw" },
257 { Opt_ignore, "ro" },
258 { Opt_ignore, "suid" },
259 { Opt_ignore, "nosuid" },
260 { Opt_ignore, "exec" },
261 { Opt_ignore, "noexec" },
262 { Opt_ignore, "nodev" },
263 { Opt_ignore, "noauto" },
264 { Opt_ignore, "dev" },
265 { Opt_ignore, "mand" },
266 { Opt_ignore, "nomand" },
David Brazdil0f672f62019-12-10 10:32:29 +0000267 { Opt_ignore, "relatime" },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000268 { Opt_ignore, "_netdev" },
David Brazdil0f672f62019-12-10 10:32:29 +0000269 { Opt_rootfs, "rootfs" },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000270
271 { Opt_err, NULL }
272};
273
274enum {
275 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
276 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
277 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
278 Opt_sec_ntlmv2i, Opt_sec_lanman,
279 Opt_sec_none,
280
281 Opt_sec_err
282};
283
284static const match_table_t cifs_secflavor_tokens = {
285 { Opt_sec_krb5, "krb5" },
286 { Opt_sec_krb5i, "krb5i" },
287 { Opt_sec_krb5p, "krb5p" },
288 { Opt_sec_ntlmsspi, "ntlmsspi" },
289 { Opt_sec_ntlmssp, "ntlmssp" },
290 { Opt_ntlm, "ntlm" },
291 { Opt_sec_ntlmi, "ntlmi" },
292 { Opt_sec_ntlmv2, "nontlm" },
293 { Opt_sec_ntlmv2, "ntlmv2" },
294 { Opt_sec_ntlmv2i, "ntlmv2i" },
295 { Opt_sec_lanman, "lanman" },
296 { Opt_sec_none, "none" },
297
298 { Opt_sec_err, NULL }
299};
300
301/* cache flavors */
302enum {
303 Opt_cache_loose,
304 Opt_cache_strict,
305 Opt_cache_none,
David Brazdil0f672f62019-12-10 10:32:29 +0000306 Opt_cache_ro,
307 Opt_cache_rw,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000308 Opt_cache_err
309};
310
311static const match_table_t cifs_cacheflavor_tokens = {
312 { Opt_cache_loose, "loose" },
313 { Opt_cache_strict, "strict" },
314 { Opt_cache_none, "none" },
David Brazdil0f672f62019-12-10 10:32:29 +0000315 { Opt_cache_ro, "ro" },
316 { Opt_cache_rw, "singleclient" },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000317 { Opt_cache_err, NULL }
318};
319
320static const match_table_t cifs_smb_version_tokens = {
321 { Smb_1, SMB1_VERSION_STRING },
322 { Smb_20, SMB20_VERSION_STRING},
323 { Smb_21, SMB21_VERSION_STRING },
324 { Smb_30, SMB30_VERSION_STRING },
325 { Smb_302, SMB302_VERSION_STRING },
David Brazdil0f672f62019-12-10 10:32:29 +0000326 { Smb_302, ALT_SMB302_VERSION_STRING },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000327 { Smb_311, SMB311_VERSION_STRING },
328 { Smb_311, ALT_SMB311_VERSION_STRING },
329 { Smb_3any, SMB3ANY_VERSION_STRING },
330 { Smb_default, SMBDEFAULT_VERSION_STRING },
331 { Smb_version_err, NULL }
332};
333
334static int ip_connect(struct TCP_Server_Info *server);
335static int generic_ip_connect(struct TCP_Server_Info *server);
336static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
337static void cifs_prune_tlinks(struct work_struct *work);
David Brazdil0f672f62019-12-10 10:32:29 +0000338static char *extract_hostname(const char *unc);
339
340/*
341 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
342 * get their ip addresses changed at some point.
343 *
344 * This should be called with server->srv_mutex held.
345 */
346#ifdef CONFIG_CIFS_DFS_UPCALL
347static int reconn_set_ipaddr(struct TCP_Server_Info *server)
348{
349 int rc;
350 int len;
351 char *unc, *ipaddr = NULL;
352
353 if (!server->hostname)
354 return -EINVAL;
355
356 len = strlen(server->hostname) + 3;
357
358 unc = kmalloc(len, GFP_KERNEL);
359 if (!unc) {
360 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
361 return -ENOMEM;
362 }
363 scnprintf(unc, len, "\\\\%s", server->hostname);
364
365 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
366 kfree(unc);
367
368 if (rc < 0) {
369 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
370 __func__, server->hostname, rc);
371 return rc;
372 }
373
Olivier Deprez0e641232021-09-23 10:07:05 +0200374 spin_lock(&cifs_tcp_ses_lock);
David Brazdil0f672f62019-12-10 10:32:29 +0000375 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
376 strlen(ipaddr));
Olivier Deprez0e641232021-09-23 10:07:05 +0200377 spin_unlock(&cifs_tcp_ses_lock);
David Brazdil0f672f62019-12-10 10:32:29 +0000378 kfree(ipaddr);
379
380 return !rc ? -1 : 0;
381}
382#else
383static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
384{
385 return 0;
386}
387#endif
388
389#ifdef CONFIG_CIFS_DFS_UPCALL
390struct super_cb_data {
391 struct TCP_Server_Info *server;
Olivier Deprez0e641232021-09-23 10:07:05 +0200392 struct super_block *sb;
David Brazdil0f672f62019-12-10 10:32:29 +0000393};
394
395/* These functions must be called with server->srv_mutex held */
396
397static void super_cb(struct super_block *sb, void *arg)
398{
399 struct super_cb_data *d = arg;
400 struct cifs_sb_info *cifs_sb;
401 struct cifs_tcon *tcon;
402
Olivier Deprez0e641232021-09-23 10:07:05 +0200403 if (d->sb)
David Brazdil0f672f62019-12-10 10:32:29 +0000404 return;
405
406 cifs_sb = CIFS_SB(sb);
407 tcon = cifs_sb_master_tcon(cifs_sb);
408 if (tcon->ses->server == d->server)
Olivier Deprez0e641232021-09-23 10:07:05 +0200409 d->sb = sb;
David Brazdil0f672f62019-12-10 10:32:29 +0000410}
411
Olivier Deprez0e641232021-09-23 10:07:05 +0200412static struct super_block *get_tcp_super(struct TCP_Server_Info *server)
David Brazdil0f672f62019-12-10 10:32:29 +0000413{
414 struct super_cb_data d = {
415 .server = server,
Olivier Deprez0e641232021-09-23 10:07:05 +0200416 .sb = NULL,
David Brazdil0f672f62019-12-10 10:32:29 +0000417 };
418
419 iterate_supers_type(&cifs_fs_type, super_cb, &d);
Olivier Deprez0e641232021-09-23 10:07:05 +0200420
421 if (unlikely(!d.sb))
422 return ERR_PTR(-ENOENT);
423 /*
424 * Grab an active reference in order to prevent automounts (DFS links)
425 * of expiring and then freeing up our cifs superblock pointer while
426 * we're doing failover.
427 */
428 cifs_sb_active(d.sb);
429 return d.sb;
430}
431
432static inline void put_tcp_super(struct super_block *sb)
433{
434 if (!IS_ERR_OR_NULL(sb))
435 cifs_sb_deactive(sb);
David Brazdil0f672f62019-12-10 10:32:29 +0000436}
437
438static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
439 struct cifs_sb_info *cifs_sb,
440 struct dfs_cache_tgt_list *tgt_list,
441 struct dfs_cache_tgt_iterator **tgt_it)
442{
443 const char *name;
444
445 if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list ||
446 !server->nr_targets)
447 return;
448
449 if (!*tgt_it) {
450 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
451 } else {
452 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
453 if (!*tgt_it)
454 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
455 }
456
457 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
458
459 name = dfs_cache_get_tgt_name(*tgt_it);
460
461 kfree(server->hostname);
462
463 server->hostname = extract_hostname(name);
464 if (IS_ERR(server->hostname)) {
465 cifs_dbg(FYI,
466 "%s: failed to extract hostname from target: %ld\n",
467 __func__, PTR_ERR(server->hostname));
468 }
469}
470
471static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
472 struct dfs_cache_tgt_list *tl,
473 struct dfs_cache_tgt_iterator **it)
474{
475 if (!cifs_sb->origin_fullpath)
476 return -EOPNOTSUPP;
477 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
478}
479#endif
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000480
481/*
482 * cifs tcp session reconnection
483 *
484 * mark tcp session as reconnecting so temporarily locked
485 * mark all smb sessions as reconnecting for tcp session
486 * reconnect tcp session
487 * wake up waiters on reconnection? - (not needed currently)
488 */
489int
490cifs_reconnect(struct TCP_Server_Info *server)
491{
492 int rc = 0;
493 struct list_head *tmp, *tmp2;
494 struct cifs_ses *ses;
495 struct cifs_tcon *tcon;
496 struct mid_q_entry *mid_entry;
497 struct list_head retry_list;
David Brazdil0f672f62019-12-10 10:32:29 +0000498#ifdef CONFIG_CIFS_DFS_UPCALL
Olivier Deprez0e641232021-09-23 10:07:05 +0200499 struct super_block *sb = NULL;
David Brazdil0f672f62019-12-10 10:32:29 +0000500 struct cifs_sb_info *cifs_sb = NULL;
501 struct dfs_cache_tgt_list tgt_list = {0};
502 struct dfs_cache_tgt_iterator *tgt_it = NULL;
503#endif
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000504
505 spin_lock(&GlobalMid_Lock);
David Brazdil0f672f62019-12-10 10:32:29 +0000506 server->nr_targets = 1;
507#ifdef CONFIG_CIFS_DFS_UPCALL
508 spin_unlock(&GlobalMid_Lock);
Olivier Deprez0e641232021-09-23 10:07:05 +0200509 sb = get_tcp_super(server);
510 if (IS_ERR(sb)) {
511 rc = PTR_ERR(sb);
David Brazdil0f672f62019-12-10 10:32:29 +0000512 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
513 __func__, rc);
Olivier Deprez0e641232021-09-23 10:07:05 +0200514 sb = NULL;
David Brazdil0f672f62019-12-10 10:32:29 +0000515 } else {
Olivier Deprez0e641232021-09-23 10:07:05 +0200516 cifs_sb = CIFS_SB(sb);
517
David Brazdil0f672f62019-12-10 10:32:29 +0000518 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
519 if (rc && (rc != -EOPNOTSUPP)) {
520 cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
521 __func__);
522 } else {
523 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
524 }
525 }
526 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
527 server->nr_targets);
528 spin_lock(&GlobalMid_Lock);
529#endif
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000530 if (server->tcpStatus == CifsExiting) {
531 /* the demux thread will exit normally
532 next time through the loop */
533 spin_unlock(&GlobalMid_Lock);
Olivier Deprez0e641232021-09-23 10:07:05 +0200534#ifdef CONFIG_CIFS_DFS_UPCALL
535 dfs_cache_free_tgts(&tgt_list);
536 put_tcp_super(sb);
537#endif
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000538 return rc;
539 } else
540 server->tcpStatus = CifsNeedReconnect;
541 spin_unlock(&GlobalMid_Lock);
542 server->maxBuf = 0;
543 server->max_read = 0;
544
David Brazdil0f672f62019-12-10 10:32:29 +0000545 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000546 trace_smb3_reconnect(server->CurrentMid, server->hostname);
547
548 /* before reconnecting the tcp session, mark the smb session (uid)
549 and the tid bad so they are not used until reconnected */
550 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
551 __func__);
552 spin_lock(&cifs_tcp_ses_lock);
553 list_for_each(tmp, &server->smb_ses_list) {
554 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
555 ses->need_reconnect = true;
556 list_for_each(tmp2, &ses->tcon_list) {
557 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
558 tcon->need_reconnect = true;
559 }
560 if (ses->tcon_ipc)
561 ses->tcon_ipc->need_reconnect = true;
562 }
563 spin_unlock(&cifs_tcp_ses_lock);
564
565 /* do not want to be sending data on a socket we are freeing */
566 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
567 mutex_lock(&server->srv_mutex);
568 if (server->ssocket) {
569 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
570 server->ssocket->state, server->ssocket->flags);
571 kernel_sock_shutdown(server->ssocket, SHUT_WR);
572 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
573 server->ssocket->state, server->ssocket->flags);
574 sock_release(server->ssocket);
575 server->ssocket = NULL;
576 }
577 server->sequence_number = 0;
578 server->session_estab = false;
579 kfree(server->session_key.response);
580 server->session_key.response = NULL;
581 server->session_key.len = 0;
582 server->lstrp = jiffies;
583
584 /* mark submitted MIDs for retry and issue callback */
585 INIT_LIST_HEAD(&retry_list);
586 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
587 spin_lock(&GlobalMid_Lock);
588 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
589 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
David Brazdil0f672f62019-12-10 10:32:29 +0000590 kref_get(&mid_entry->refcount);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000591 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
592 mid_entry->mid_state = MID_RETRY_NEEDED;
593 list_move(&mid_entry->qhead, &retry_list);
David Brazdil0f672f62019-12-10 10:32:29 +0000594 mid_entry->mid_flags |= MID_DELETED;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000595 }
596 spin_unlock(&GlobalMid_Lock);
597 mutex_unlock(&server->srv_mutex);
598
599 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
600 list_for_each_safe(tmp, tmp2, &retry_list) {
601 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
602 list_del_init(&mid_entry->qhead);
603 mid_entry->callback(mid_entry);
David Brazdil0f672f62019-12-10 10:32:29 +0000604 cifs_mid_q_entry_release(mid_entry);
605 }
606
607 if (cifs_rdma_enabled(server)) {
608 mutex_lock(&server->srv_mutex);
609 smbd_destroy(server);
610 mutex_unlock(&server->srv_mutex);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000611 }
612
613 do {
614 try_to_freeze();
615
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000616 mutex_lock(&server->srv_mutex);
Olivier Deprez0e641232021-09-23 10:07:05 +0200617#ifdef CONFIG_CIFS_DFS_UPCALL
David Brazdil0f672f62019-12-10 10:32:29 +0000618 /*
619 * Set up next DFS target server (if any) for reconnect. If DFS
620 * feature is disabled, then we will retry last server we
621 * connected to before.
622 */
Olivier Deprez0e641232021-09-23 10:07:05 +0200623 reconn_inval_dfs_target(server, cifs_sb, &tgt_list, &tgt_it);
624#endif
625 rc = reconn_set_ipaddr(server);
626 if (rc) {
627 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
628 __func__, rc);
629 }
630
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000631 if (cifs_rdma_enabled(server))
632 rc = smbd_reconnect(server);
633 else
634 rc = generic_ip_connect(server);
635 if (rc) {
636 cifs_dbg(FYI, "reconnect error %d\n", rc);
637 mutex_unlock(&server->srv_mutex);
638 msleep(3000);
639 } else {
640 atomic_inc(&tcpSesReconnectCount);
David Brazdil0f672f62019-12-10 10:32:29 +0000641 set_credits(server, 1);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000642 spin_lock(&GlobalMid_Lock);
643 if (server->tcpStatus != CifsExiting)
644 server->tcpStatus = CifsNeedNegotiate;
645 spin_unlock(&GlobalMid_Lock);
646 mutex_unlock(&server->srv_mutex);
647 }
648 } while (server->tcpStatus == CifsNeedReconnect);
649
David Brazdil0f672f62019-12-10 10:32:29 +0000650#ifdef CONFIG_CIFS_DFS_UPCALL
651 if (tgt_it) {
652 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
653 tgt_it);
654 if (rc) {
655 cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
656 __func__, rc);
657 }
658 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
659 if (rc) {
660 cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
661 __func__, rc);
662 }
663 dfs_cache_free_tgts(&tgt_list);
Olivier Deprez0e641232021-09-23 10:07:05 +0200664
David Brazdil0f672f62019-12-10 10:32:29 +0000665 }
Olivier Deprez0e641232021-09-23 10:07:05 +0200666
667 put_tcp_super(sb);
David Brazdil0f672f62019-12-10 10:32:29 +0000668#endif
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000669 if (server->tcpStatus == CifsNeedNegotiate)
670 mod_delayed_work(cifsiod_wq, &server->echo, 0);
671
672 return rc;
673}
674
675static void
676cifs_echo_request(struct work_struct *work)
677{
678 int rc;
679 struct TCP_Server_Info *server = container_of(work,
680 struct TCP_Server_Info, echo.work);
681 unsigned long echo_interval;
682
683 /*
684 * If we need to renegotiate, set echo interval to zero to
685 * immediately call echo service where we can renegotiate.
686 */
687 if (server->tcpStatus == CifsNeedNegotiate)
688 echo_interval = 0;
689 else
690 echo_interval = server->echo_interval;
691
692 /*
693 * We cannot send an echo if it is disabled.
694 * Also, no need to ping if we got a response recently.
695 */
696
697 if (server->tcpStatus == CifsNeedReconnect ||
698 server->tcpStatus == CifsExiting ||
699 server->tcpStatus == CifsNew ||
700 (server->ops->can_echo && !server->ops->can_echo(server)) ||
701 time_before(jiffies, server->lstrp + echo_interval - HZ))
702 goto requeue_echo;
703
704 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
705 if (rc)
706 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
707 server->hostname);
708
709requeue_echo:
710 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
711}
712
713static bool
714allocate_buffers(struct TCP_Server_Info *server)
715{
716 if (!server->bigbuf) {
717 server->bigbuf = (char *)cifs_buf_get();
718 if (!server->bigbuf) {
David Brazdil0f672f62019-12-10 10:32:29 +0000719 cifs_server_dbg(VFS, "No memory for large SMB response\n");
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000720 msleep(3000);
721 /* retry will check if exiting */
722 return false;
723 }
724 } else if (server->large_buf) {
725 /* we are reusing a dirty large buf, clear its start */
726 memset(server->bigbuf, 0, HEADER_SIZE(server));
727 }
728
729 if (!server->smallbuf) {
730 server->smallbuf = (char *)cifs_small_buf_get();
731 if (!server->smallbuf) {
David Brazdil0f672f62019-12-10 10:32:29 +0000732 cifs_server_dbg(VFS, "No memory for SMB response\n");
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000733 msleep(1000);
734 /* retry will check if exiting */
735 return false;
736 }
737 /* beginning of smb buffer is cleared in our buf_get */
738 } else {
739 /* if existing small buf clear beginning */
740 memset(server->smallbuf, 0, HEADER_SIZE(server));
741 }
742
743 return true;
744}
745
746static bool
747server_unresponsive(struct TCP_Server_Info *server)
748{
749 /*
David Brazdil0f672f62019-12-10 10:32:29 +0000750 * We need to wait 3 echo intervals to make sure we handle such
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000751 * situations right:
752 * 1s client sends a normal SMB request
753 * 2s client gets a response
754 * 30s echo workqueue job pops, and decides we got a response recently
755 * and don't need to send another
756 * ...
757 * 65s kernel_recvmsg times out, and we see that we haven't gotten
758 * a response in >60s.
759 */
760 if ((server->tcpStatus == CifsGood ||
761 server->tcpStatus == CifsNeedNegotiate) &&
David Brazdil0f672f62019-12-10 10:32:29 +0000762 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
763 cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
764 (3 * server->echo_interval) / HZ);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000765 cifs_reconnect(server);
766 wake_up(&server->response_q);
767 return true;
768 }
769
770 return false;
771}
772
David Brazdil0f672f62019-12-10 10:32:29 +0000773static inline bool
774zero_credits(struct TCP_Server_Info *server)
775{
776 int val;
777
778 spin_lock(&server->req_lock);
779 val = server->credits + server->echo_credits + server->oplock_credits;
780 if (server->in_flight == 0 && val == 0) {
781 spin_unlock(&server->req_lock);
782 return true;
783 }
784 spin_unlock(&server->req_lock);
785 return false;
786}
787
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000788static int
789cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
790{
791 int length = 0;
792 int total_read;
793
794 smb_msg->msg_control = NULL;
795 smb_msg->msg_controllen = 0;
796
797 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
798 try_to_freeze();
799
David Brazdil0f672f62019-12-10 10:32:29 +0000800 /* reconnect if no credits and no requests in flight */
801 if (zero_credits(server)) {
802 cifs_reconnect(server);
803 return -ECONNABORTED;
804 }
805
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000806 if (server_unresponsive(server))
807 return -ECONNABORTED;
808 if (cifs_rdma_enabled(server) && server->smbd_conn)
809 length = smbd_recv(server->smbd_conn, smb_msg);
810 else
811 length = sock_recvmsg(server->ssocket, smb_msg, 0);
812
813 if (server->tcpStatus == CifsExiting)
814 return -ESHUTDOWN;
815
816 if (server->tcpStatus == CifsNeedReconnect) {
817 cifs_reconnect(server);
818 return -ECONNABORTED;
819 }
820
821 if (length == -ERESTARTSYS ||
822 length == -EAGAIN ||
823 length == -EINTR) {
824 /*
825 * Minimum sleep to prevent looping, allowing socket
826 * to clear and app threads to set tcpStatus
827 * CifsNeedReconnect if server hung.
828 */
829 usleep_range(1000, 2000);
830 length = 0;
831 continue;
832 }
833
834 if (length <= 0) {
835 cifs_dbg(FYI, "Received no data or error: %d\n", length);
836 cifs_reconnect(server);
837 return -ECONNABORTED;
838 }
839 }
840 return total_read;
841}
842
843int
844cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
845 unsigned int to_read)
846{
847 struct msghdr smb_msg;
848 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Brazdil0f672f62019-12-10 10:32:29 +0000849 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000850
851 return cifs_readv_from_socket(server, &smb_msg);
852}
853
854int
855cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
856 unsigned int page_offset, unsigned int to_read)
857{
858 struct msghdr smb_msg;
859 struct bio_vec bv = {
860 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Brazdil0f672f62019-12-10 10:32:29 +0000861 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000862 return cifs_readv_from_socket(server, &smb_msg);
863}
864
865static bool
866is_smb_response(struct TCP_Server_Info *server, unsigned char type)
867{
868 /*
869 * The first byte big endian of the length field,
870 * is actually not part of the length but the type
871 * with the most common, zero, as regular data.
872 */
873 switch (type) {
874 case RFC1002_SESSION_MESSAGE:
875 /* Regular SMB response */
876 return true;
877 case RFC1002_SESSION_KEEP_ALIVE:
878 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
879 break;
880 case RFC1002_POSITIVE_SESSION_RESPONSE:
881 cifs_dbg(FYI, "RFC 1002 positive session response\n");
882 break;
883 case RFC1002_NEGATIVE_SESSION_RESPONSE:
884 /*
885 * We get this from Windows 98 instead of an error on
886 * SMB negprot response.
887 */
888 cifs_dbg(FYI, "RFC 1002 negative session response\n");
889 /* give server a second to clean up */
890 msleep(1000);
891 /*
892 * Always try 445 first on reconnect since we get NACK
893 * on some if we ever connected to port 139 (the NACK
894 * is since we do not begin with RFC1001 session
895 * initialize frame).
896 */
897 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
898 cifs_reconnect(server);
899 wake_up(&server->response_q);
900 break;
901 default:
David Brazdil0f672f62019-12-10 10:32:29 +0000902 cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000903 cifs_reconnect(server);
904 }
905
906 return false;
907}
908
909void
910dequeue_mid(struct mid_q_entry *mid, bool malformed)
911{
912#ifdef CONFIG_CIFS_STATS2
913 mid->when_received = jiffies;
914#endif
915 spin_lock(&GlobalMid_Lock);
916 if (!malformed)
917 mid->mid_state = MID_RESPONSE_RECEIVED;
918 else
919 mid->mid_state = MID_RESPONSE_MALFORMED;
920 /*
921 * Trying to handle/dequeue a mid after the send_recv()
922 * function has finished processing it is a bug.
923 */
924 if (mid->mid_flags & MID_DELETED)
925 printk_once(KERN_WARNING
926 "trying to dequeue a deleted mid\n");
David Brazdil0f672f62019-12-10 10:32:29 +0000927 else {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000928 list_del_init(&mid->qhead);
David Brazdil0f672f62019-12-10 10:32:29 +0000929 mid->mid_flags |= MID_DELETED;
930 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000931 spin_unlock(&GlobalMid_Lock);
932}
933
Olivier Deprez0e641232021-09-23 10:07:05 +0200934static unsigned int
935smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
936{
937 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
938
939 /*
940 * SMB1 does not use credits.
941 */
942 if (server->vals->header_preamble_size)
943 return 0;
944
945 return le16_to_cpu(shdr->CreditRequest);
946}
947
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000948static void
949handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
950 char *buf, int malformed)
951{
952 if (server->ops->check_trans2 &&
953 server->ops->check_trans2(mid, server, buf, malformed))
954 return;
Olivier Deprez0e641232021-09-23 10:07:05 +0200955 mid->credits_received = smb2_get_credits_from_hdr(buf, server);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000956 mid->resp_buf = buf;
957 mid->large_buf = server->large_buf;
958 /* Was previous buf put in mpx struct for multi-rsp? */
959 if (!mid->multiRsp) {
960 /* smb buffer will be freed by user thread */
961 if (server->large_buf)
962 server->bigbuf = NULL;
963 else
964 server->smallbuf = NULL;
965 }
966 dequeue_mid(mid, malformed);
967}
968
969static void clean_demultiplex_info(struct TCP_Server_Info *server)
970{
971 int length;
972
973 /* take it off the list, if it's not already */
974 spin_lock(&cifs_tcp_ses_lock);
975 list_del_init(&server->tcp_ses_list);
976 spin_unlock(&cifs_tcp_ses_lock);
977
Olivier Deprez0e641232021-09-23 10:07:05 +0200978 cancel_delayed_work_sync(&server->echo);
979
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000980 spin_lock(&GlobalMid_Lock);
981 server->tcpStatus = CifsExiting;
982 spin_unlock(&GlobalMid_Lock);
983 wake_up_all(&server->response_q);
984
985 /* check if we have blocked requests that need to free */
986 spin_lock(&server->req_lock);
987 if (server->credits <= 0)
988 server->credits = 1;
989 spin_unlock(&server->req_lock);
990 /*
991 * Although there should not be any requests blocked on this queue it
992 * can not hurt to be paranoid and try to wake up requests that may
993 * haven been blocked when more than 50 at time were on the wire to the
994 * same server - they now will see the session is in exit state and get
995 * out of SendReceive.
996 */
997 wake_up_all(&server->request_q);
998 /* give those requests time to exit */
999 msleep(125);
David Brazdil0f672f62019-12-10 10:32:29 +00001000 if (cifs_rdma_enabled(server))
1001 smbd_destroy(server);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001002 if (server->ssocket) {
1003 sock_release(server->ssocket);
1004 server->ssocket = NULL;
1005 }
1006
1007 if (!list_empty(&server->pending_mid_q)) {
1008 struct list_head dispose_list;
1009 struct mid_q_entry *mid_entry;
1010 struct list_head *tmp, *tmp2;
1011
1012 INIT_LIST_HEAD(&dispose_list);
1013 spin_lock(&GlobalMid_Lock);
1014 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
1015 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
1016 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
David Brazdil0f672f62019-12-10 10:32:29 +00001017 kref_get(&mid_entry->refcount);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001018 mid_entry->mid_state = MID_SHUTDOWN;
1019 list_move(&mid_entry->qhead, &dispose_list);
David Brazdil0f672f62019-12-10 10:32:29 +00001020 mid_entry->mid_flags |= MID_DELETED;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001021 }
1022 spin_unlock(&GlobalMid_Lock);
1023
1024 /* now walk dispose list and issue callbacks */
1025 list_for_each_safe(tmp, tmp2, &dispose_list) {
1026 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
1027 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
1028 list_del_init(&mid_entry->qhead);
1029 mid_entry->callback(mid_entry);
David Brazdil0f672f62019-12-10 10:32:29 +00001030 cifs_mid_q_entry_release(mid_entry);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001031 }
1032 /* 1/8th of sec is more than enough time for them to exit */
1033 msleep(125);
1034 }
1035
1036 if (!list_empty(&server->pending_mid_q)) {
1037 /*
1038 * mpx threads have not exited yet give them at least the smb
1039 * send timeout time for long ops.
1040 *
1041 * Due to delays on oplock break requests, we need to wait at
1042 * least 45 seconds before giving up on a request getting a
1043 * response and going ahead and killing cifsd.
1044 */
1045 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
1046 msleep(46000);
1047 /*
1048 * If threads still have not exited they are probably never
1049 * coming home not much else we can do but free the memory.
1050 */
1051 }
1052
1053 kfree(server->hostname);
1054 kfree(server);
1055
1056 length = atomic_dec_return(&tcpSesAllocCount);
1057 if (length > 0)
1058 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
1059}
1060
1061static int
1062standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1063{
1064 int length;
1065 char *buf = server->smallbuf;
1066 unsigned int pdu_length = server->pdu_size;
1067
1068 /* make sure this will fit in a large buffer */
1069 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
1070 server->vals->header_preamble_size) {
David Brazdil0f672f62019-12-10 10:32:29 +00001071 cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001072 cifs_reconnect(server);
1073 wake_up(&server->response_q);
1074 return -ECONNABORTED;
1075 }
1076
1077 /* switch to large buffer if too big for a small one */
1078 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
1079 server->large_buf = true;
1080 memcpy(server->bigbuf, buf, server->total_read);
1081 buf = server->bigbuf;
1082 }
1083
1084 /* now read the rest */
1085 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
1086 pdu_length - HEADER_SIZE(server) + 1
1087 + server->vals->header_preamble_size);
1088
1089 if (length < 0)
1090 return length;
1091 server->total_read += length;
1092
1093 dump_smb(buf, server->total_read);
1094
1095 return cifs_handle_standard(server, mid);
1096}
1097
1098int
1099cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1100{
1101 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1102 int length;
1103
1104 /*
1105 * We know that we received enough to get to the MID as we
1106 * checked the pdu_length earlier. Now check to see
1107 * if the rest of the header is OK. We borrow the length
1108 * var for the rest of the loop to avoid a new stack var.
1109 *
1110 * 48 bytes is enough to display the header and a little bit
1111 * into the payload for debugging purposes.
1112 */
1113 length = server->ops->check_message(buf, server->total_read, server);
1114 if (length != 0)
1115 cifs_dump_mem("Bad SMB: ", buf,
1116 min_t(unsigned int, server->total_read, 48));
1117
1118 if (server->ops->is_session_expired &&
1119 server->ops->is_session_expired(buf)) {
1120 cifs_reconnect(server);
1121 wake_up(&server->response_q);
1122 return -1;
1123 }
1124
1125 if (server->ops->is_status_pending &&
David Brazdil0f672f62019-12-10 10:32:29 +00001126 server->ops->is_status_pending(buf, server))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001127 return -1;
1128
1129 if (!mid)
1130 return length;
1131
1132 handle_mid(mid, server, buf, length);
1133 return 0;
1134}
1135
David Brazdil0f672f62019-12-10 10:32:29 +00001136static void
1137smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
1138{
1139 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
1140
1141 /*
1142 * SMB1 does not use credits.
1143 */
1144 if (server->vals->header_preamble_size)
1145 return;
1146
1147 if (shdr->CreditRequest) {
1148 spin_lock(&server->req_lock);
1149 server->credits += le16_to_cpu(shdr->CreditRequest);
1150 spin_unlock(&server->req_lock);
1151 wake_up(&server->request_q);
1152 }
1153}
1154
1155
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001156static int
1157cifs_demultiplex_thread(void *p)
1158{
1159 int i, num_mids, length;
1160 struct TCP_Server_Info *server = p;
1161 unsigned int pdu_length;
1162 unsigned int next_offset;
1163 char *buf = NULL;
1164 struct task_struct *task_to_wake = NULL;
1165 struct mid_q_entry *mids[MAX_COMPOUND];
1166 char *bufs[MAX_COMPOUND];
1167
1168 current->flags |= PF_MEMALLOC;
1169 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
1170
1171 length = atomic_inc_return(&tcpSesAllocCount);
1172 if (length > 1)
1173 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
1174
1175 set_freezable();
David Brazdil0f672f62019-12-10 10:32:29 +00001176 allow_kernel_signal(SIGKILL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001177 while (server->tcpStatus != CifsExiting) {
1178 if (try_to_freeze())
1179 continue;
1180
1181 if (!allocate_buffers(server))
1182 continue;
1183
1184 server->large_buf = false;
1185 buf = server->smallbuf;
1186 pdu_length = 4; /* enough to get RFC1001 header */
1187
1188 length = cifs_read_from_socket(server, buf, pdu_length);
1189 if (length < 0)
1190 continue;
1191
1192 if (server->vals->header_preamble_size == 0)
1193 server->total_read = 0;
1194 else
1195 server->total_read = length;
1196
1197 /*
1198 * The right amount was read from socket - 4 bytes,
1199 * so we can now interpret the length field.
1200 */
1201 pdu_length = get_rfc1002_length(buf);
1202
1203 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
1204 if (!is_smb_response(server, buf[0]))
1205 continue;
1206next_pdu:
1207 server->pdu_size = pdu_length;
1208
1209 /* make sure we have enough to get to the MID */
1210 if (server->pdu_size < HEADER_SIZE(server) - 1 -
1211 server->vals->header_preamble_size) {
David Brazdil0f672f62019-12-10 10:32:29 +00001212 cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001213 server->pdu_size);
1214 cifs_reconnect(server);
1215 wake_up(&server->response_q);
1216 continue;
1217 }
1218
1219 /* read down to the MID */
1220 length = cifs_read_from_socket(server,
1221 buf + server->vals->header_preamble_size,
1222 HEADER_SIZE(server) - 1
1223 - server->vals->header_preamble_size);
1224 if (length < 0)
1225 continue;
1226 server->total_read += length;
1227
1228 if (server->ops->next_header) {
1229 next_offset = server->ops->next_header(buf);
1230 if (next_offset)
1231 server->pdu_size = next_offset;
1232 }
1233
1234 memset(mids, 0, sizeof(mids));
1235 memset(bufs, 0, sizeof(bufs));
1236 num_mids = 0;
1237
1238 if (server->ops->is_transform_hdr &&
1239 server->ops->receive_transform &&
1240 server->ops->is_transform_hdr(buf)) {
1241 length = server->ops->receive_transform(server,
1242 mids,
1243 bufs,
1244 &num_mids);
1245 } else {
1246 mids[0] = server->ops->find_mid(server, buf);
1247 bufs[0] = buf;
1248 num_mids = 1;
1249
1250 if (!mids[0] || !mids[0]->receive)
1251 length = standard_receive3(server, mids[0]);
1252 else
1253 length = mids[0]->receive(server, mids[0]);
1254 }
1255
1256 if (length < 0) {
1257 for (i = 0; i < num_mids; i++)
1258 if (mids[i])
1259 cifs_mid_q_entry_release(mids[i]);
1260 continue;
1261 }
1262
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001263 server->lstrp = jiffies;
1264
1265 for (i = 0; i < num_mids; i++) {
1266 if (mids[i] != NULL) {
1267 mids[i]->resp_buf_size = server->pdu_size;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001268
1269 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1270 mids[i]->callback(mids[i]);
1271
1272 cifs_mid_q_entry_release(mids[i]);
1273 } else if (server->ops->is_oplock_break &&
1274 server->ops->is_oplock_break(bufs[i],
1275 server)) {
David Brazdil0f672f62019-12-10 10:32:29 +00001276 smb2_add_credits_from_hdr(bufs[i], server);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001277 cifs_dbg(FYI, "Received oplock break\n");
1278 } else {
David Brazdil0f672f62019-12-10 10:32:29 +00001279 cifs_server_dbg(VFS, "No task to wake, unknown frame "
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001280 "received! NumMids %d\n",
1281 atomic_read(&midCount));
1282 cifs_dump_mem("Received Data is: ", bufs[i],
1283 HEADER_SIZE(server));
David Brazdil0f672f62019-12-10 10:32:29 +00001284 smb2_add_credits_from_hdr(bufs[i], server);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001285#ifdef CONFIG_CIFS_DEBUG2
1286 if (server->ops->dump_detail)
1287 server->ops->dump_detail(bufs[i],
1288 server);
1289 cifs_dump_mids(server);
1290#endif /* CIFS_DEBUG2 */
1291 }
1292 }
1293
1294 if (pdu_length > server->pdu_size) {
1295 if (!allocate_buffers(server))
1296 continue;
1297 pdu_length -= server->pdu_size;
1298 server->total_read = 0;
1299 server->large_buf = false;
1300 buf = server->smallbuf;
1301 goto next_pdu;
1302 }
1303 } /* end while !EXITING */
1304
1305 /* buffer usually freed in free_mid - need to free it here on exit */
1306 cifs_buf_release(server->bigbuf);
1307 if (server->smallbuf) /* no sense logging a debug message if NULL */
1308 cifs_small_buf_release(server->smallbuf);
1309
1310 task_to_wake = xchg(&server->tsk, NULL);
1311 clean_demultiplex_info(server);
1312
1313 /* if server->tsk was NULL then wait for a signal before exiting */
1314 if (!task_to_wake) {
1315 set_current_state(TASK_INTERRUPTIBLE);
1316 while (!signal_pending(current)) {
1317 schedule();
1318 set_current_state(TASK_INTERRUPTIBLE);
1319 }
1320 set_current_state(TASK_RUNNING);
1321 }
1322
1323 module_put_and_exit(0);
1324}
1325
1326/* extract the host portion of the UNC string */
1327static char *
1328extract_hostname(const char *unc)
1329{
1330 const char *src;
1331 char *dst, *delim;
1332 unsigned int len;
1333
1334 /* skip double chars at beginning of string */
1335 /* BB: check validity of these bytes? */
David Brazdil0f672f62019-12-10 10:32:29 +00001336 if (strlen(unc) < 3)
1337 return ERR_PTR(-EINVAL);
1338 for (src = unc; *src && *src == '\\'; src++)
1339 ;
1340 if (!*src)
1341 return ERR_PTR(-EINVAL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001342
1343 /* delimiter between hostname and sharename is always '\\' now */
1344 delim = strchr(src, '\\');
1345 if (!delim)
1346 return ERR_PTR(-EINVAL);
1347
1348 len = delim - src;
1349 dst = kmalloc((len + 1), GFP_KERNEL);
1350 if (dst == NULL)
1351 return ERR_PTR(-ENOMEM);
1352
1353 memcpy(dst, src, len);
1354 dst[len] = '\0';
1355
1356 return dst;
1357}
1358
1359static int get_option_ul(substring_t args[], unsigned long *option)
1360{
1361 int rc;
1362 char *string;
1363
1364 string = match_strdup(args);
1365 if (string == NULL)
1366 return -ENOMEM;
1367 rc = kstrtoul(string, 0, option);
1368 kfree(string);
1369
1370 return rc;
1371}
1372
1373static int get_option_uid(substring_t args[], kuid_t *result)
1374{
1375 unsigned long value;
1376 kuid_t uid;
1377 int rc;
1378
1379 rc = get_option_ul(args, &value);
1380 if (rc)
1381 return rc;
1382
1383 uid = make_kuid(current_user_ns(), value);
1384 if (!uid_valid(uid))
1385 return -EINVAL;
1386
1387 *result = uid;
1388 return 0;
1389}
1390
1391static int get_option_gid(substring_t args[], kgid_t *result)
1392{
1393 unsigned long value;
1394 kgid_t gid;
1395 int rc;
1396
1397 rc = get_option_ul(args, &value);
1398 if (rc)
1399 return rc;
1400
1401 gid = make_kgid(current_user_ns(), value);
1402 if (!gid_valid(gid))
1403 return -EINVAL;
1404
1405 *result = gid;
1406 return 0;
1407}
1408
1409static int cifs_parse_security_flavors(char *value,
1410 struct smb_vol *vol)
1411{
1412
1413 substring_t args[MAX_OPT_ARGS];
1414
1415 /*
1416 * With mount options, the last one should win. Reset any existing
1417 * settings back to default.
1418 */
1419 vol->sectype = Unspecified;
1420 vol->sign = false;
1421
1422 switch (match_token(value, cifs_secflavor_tokens, args)) {
1423 case Opt_sec_krb5p:
1424 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1425 return 1;
1426 case Opt_sec_krb5i:
1427 vol->sign = true;
1428 /* Fallthrough */
1429 case Opt_sec_krb5:
1430 vol->sectype = Kerberos;
1431 break;
1432 case Opt_sec_ntlmsspi:
1433 vol->sign = true;
1434 /* Fallthrough */
1435 case Opt_sec_ntlmssp:
1436 vol->sectype = RawNTLMSSP;
1437 break;
1438 case Opt_sec_ntlmi:
1439 vol->sign = true;
1440 /* Fallthrough */
1441 case Opt_ntlm:
1442 vol->sectype = NTLM;
1443 break;
1444 case Opt_sec_ntlmv2i:
1445 vol->sign = true;
1446 /* Fallthrough */
1447 case Opt_sec_ntlmv2:
1448 vol->sectype = NTLMv2;
1449 break;
1450#ifdef CONFIG_CIFS_WEAK_PW_HASH
1451 case Opt_sec_lanman:
1452 vol->sectype = LANMAN;
1453 break;
1454#endif
1455 case Opt_sec_none:
1456 vol->nullauth = 1;
1457 break;
1458 default:
1459 cifs_dbg(VFS, "bad security option: %s\n", value);
1460 return 1;
1461 }
1462
1463 return 0;
1464}
1465
1466static int
1467cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1468{
1469 substring_t args[MAX_OPT_ARGS];
1470
1471 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1472 case Opt_cache_loose:
1473 vol->direct_io = false;
1474 vol->strict_io = false;
David Brazdil0f672f62019-12-10 10:32:29 +00001475 vol->cache_ro = false;
1476 vol->cache_rw = false;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001477 break;
1478 case Opt_cache_strict:
1479 vol->direct_io = false;
1480 vol->strict_io = true;
David Brazdil0f672f62019-12-10 10:32:29 +00001481 vol->cache_ro = false;
1482 vol->cache_rw = false;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001483 break;
1484 case Opt_cache_none:
1485 vol->direct_io = true;
1486 vol->strict_io = false;
David Brazdil0f672f62019-12-10 10:32:29 +00001487 vol->cache_ro = false;
1488 vol->cache_rw = false;
1489 break;
1490 case Opt_cache_ro:
1491 vol->direct_io = false;
1492 vol->strict_io = false;
1493 vol->cache_ro = true;
1494 vol->cache_rw = false;
1495 break;
1496 case Opt_cache_rw:
1497 vol->direct_io = false;
1498 vol->strict_io = false;
1499 vol->cache_ro = false;
1500 vol->cache_rw = true;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001501 break;
1502 default:
1503 cifs_dbg(VFS, "bad cache= option: %s\n", value);
1504 return 1;
1505 }
1506 return 0;
1507}
1508
1509static int
1510cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
1511{
1512 substring_t args[MAX_OPT_ARGS];
1513
1514 switch (match_token(value, cifs_smb_version_tokens, args)) {
1515#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
1516 case Smb_1:
1517 if (disable_legacy_dialects) {
1518 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1519 return 1;
1520 }
1521 if (is_smb3) {
1522 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1523 return 1;
1524 }
1525 vol->ops = &smb1_operations;
1526 vol->vals = &smb1_values;
1527 break;
1528 case Smb_20:
1529 if (disable_legacy_dialects) {
1530 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1531 return 1;
1532 }
1533 if (is_smb3) {
1534 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1535 return 1;
1536 }
1537 vol->ops = &smb20_operations;
1538 vol->vals = &smb20_values;
1539 break;
1540#else
1541 case Smb_1:
1542 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1543 return 1;
1544 case Smb_20:
1545 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1546 return 1;
1547#endif /* CIFS_ALLOW_INSECURE_LEGACY */
1548 case Smb_21:
1549 vol->ops = &smb21_operations;
1550 vol->vals = &smb21_values;
1551 break;
1552 case Smb_30:
1553 vol->ops = &smb30_operations;
1554 vol->vals = &smb30_values;
1555 break;
1556 case Smb_302:
1557 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1558 vol->vals = &smb302_values;
1559 break;
1560 case Smb_311:
1561 vol->ops = &smb311_operations;
1562 vol->vals = &smb311_values;
1563 break;
1564 case Smb_3any:
1565 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1566 vol->vals = &smb3any_values;
1567 break;
1568 case Smb_default:
1569 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1570 vol->vals = &smbdefault_values;
1571 break;
1572 default:
1573 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
1574 return 1;
1575 }
1576 return 0;
1577}
1578
1579/*
1580 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1581 * fields with the result. Returns 0 on success and an error otherwise.
1582 */
1583static int
1584cifs_parse_devname(const char *devname, struct smb_vol *vol)
1585{
1586 char *pos;
1587 const char *delims = "/\\";
1588 size_t len;
1589
David Brazdil0f672f62019-12-10 10:32:29 +00001590 if (unlikely(!devname || !*devname)) {
1591 cifs_dbg(VFS, "Device name not specified.\n");
1592 return -EINVAL;
1593 }
1594
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001595 /* make sure we have a valid UNC double delimiter prefix */
1596 len = strspn(devname, delims);
1597 if (len != 2)
1598 return -EINVAL;
1599
1600 /* find delimiter between host and sharename */
1601 pos = strpbrk(devname + 2, delims);
1602 if (!pos)
1603 return -EINVAL;
1604
1605 /* skip past delimiter */
1606 ++pos;
1607
1608 /* now go until next delimiter or end of string */
1609 len = strcspn(pos, delims);
1610
1611 /* move "pos" up to delimiter or NULL */
1612 pos += len;
1613 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1614 if (!vol->UNC)
1615 return -ENOMEM;
1616
1617 convert_delimiter(vol->UNC, '\\');
1618
1619 /* skip any delimiter */
1620 if (*pos == '/' || *pos == '\\')
1621 pos++;
1622
1623 /* If pos is NULL then no prepath */
1624 if (!*pos)
1625 return 0;
1626
1627 vol->prepath = kstrdup(pos, GFP_KERNEL);
1628 if (!vol->prepath)
1629 return -ENOMEM;
1630
1631 return 0;
1632}
1633
1634static int
1635cifs_parse_mount_options(const char *mountdata, const char *devname,
1636 struct smb_vol *vol, bool is_smb3)
1637{
1638 char *data, *end;
1639 char *mountdata_copy = NULL, *options;
1640 unsigned int temp_len, i, j;
1641 char separator[2];
1642 short int override_uid = -1;
1643 short int override_gid = -1;
1644 bool uid_specified = false;
1645 bool gid_specified = false;
1646 bool sloppy = false;
1647 char *invalid = NULL;
1648 char *nodename = utsname()->nodename;
1649 char *string = NULL;
1650 char *tmp_end, *value;
1651 char delim;
1652 bool got_ip = false;
1653 bool got_version = false;
1654 unsigned short port = 0;
1655 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
1656
1657 separator[0] = ',';
1658 separator[1] = 0;
1659 delim = separator[0];
1660
1661 /* ensure we always start with zeroed-out smb_vol */
1662 memset(vol, 0, sizeof(*vol));
1663
1664 /*
1665 * does not have to be perfect mapping since field is
1666 * informational, only used for servers that do not support
1667 * port 445 and it can be overridden at mount time
1668 */
1669 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1670 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
1671 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1672
1673 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1674 /* null target name indicates to use *SMBSERVR default called name
1675 if we end up sending RFC1001 session initialize */
1676 vol->target_rfc1001_name[0] = 0;
1677 vol->cred_uid = current_uid();
1678 vol->linux_uid = current_uid();
1679 vol->linux_gid = current_gid();
David Brazdil0f672f62019-12-10 10:32:29 +00001680 vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001681 /*
1682 * default to SFM style remapping of seven reserved characters
1683 * unless user overrides it or we negotiate CIFS POSIX where
1684 * it is unnecessary. Can not simultaneously use more than one mapping
1685 * since then readdir could list files that open could not open
1686 */
1687 vol->remap = true;
1688
1689 /* default to only allowing write access to owner of the mount */
1690 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1691
1692 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1693 /* default is always to request posix paths. */
1694 vol->posix_paths = 1;
1695 /* default to using server inode numbers where available */
1696 vol->server_ino = 1;
1697
1698 /* default is to use strict cifs caching semantics */
1699 vol->strict_io = true;
1700
1701 vol->actimeo = CIFS_DEF_ACTIMEO;
1702
David Brazdil0f672f62019-12-10 10:32:29 +00001703 /* Most clients set timeout to 0, allows server to use its default */
1704 vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1705
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001706 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1707 vol->ops = &smb30_operations;
1708 vol->vals = &smbdefault_values;
1709
1710 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1711
1712 if (!mountdata)
1713 goto cifs_parse_mount_err;
1714
1715 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1716 if (!mountdata_copy)
1717 goto cifs_parse_mount_err;
1718
1719 options = mountdata_copy;
1720 end = options + strlen(options);
1721
1722 if (strncmp(options, "sep=", 4) == 0) {
1723 if (options[4] != 0) {
1724 separator[0] = options[4];
1725 options += 5;
1726 } else {
1727 cifs_dbg(FYI, "Null separator not allowed\n");
1728 }
1729 }
1730 vol->backupuid_specified = false; /* no backup intent for a user */
1731 vol->backupgid_specified = false; /* no backup intent for a group */
1732
1733 switch (cifs_parse_devname(devname, vol)) {
1734 case 0:
1735 break;
1736 case -ENOMEM:
1737 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1738 goto cifs_parse_mount_err;
1739 case -EINVAL:
1740 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1741 goto cifs_parse_mount_err;
1742 default:
1743 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1744 goto cifs_parse_mount_err;
1745 }
1746
1747 while ((data = strsep(&options, separator)) != NULL) {
1748 substring_t args[MAX_OPT_ARGS];
1749 unsigned long option;
1750 int token;
1751
1752 if (!*data)
1753 continue;
1754
1755 token = match_token(data, cifs_mount_option_tokens, args);
1756
1757 switch (token) {
1758
1759 /* Ingnore the following */
1760 case Opt_ignore:
1761 break;
1762
1763 /* Boolean values */
1764 case Opt_user_xattr:
1765 vol->no_xattr = 0;
1766 break;
1767 case Opt_nouser_xattr:
1768 vol->no_xattr = 1;
1769 break;
1770 case Opt_forceuid:
1771 override_uid = 1;
1772 break;
1773 case Opt_noforceuid:
1774 override_uid = 0;
1775 break;
1776 case Opt_forcegid:
1777 override_gid = 1;
1778 break;
1779 case Opt_noforcegid:
1780 override_gid = 0;
1781 break;
1782 case Opt_noblocksend:
1783 vol->noblocksnd = 1;
1784 break;
1785 case Opt_noautotune:
1786 vol->noautotune = 1;
1787 break;
David Brazdil0f672f62019-12-10 10:32:29 +00001788 case Opt_nolease:
1789 vol->no_lease = 1;
1790 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001791 case Opt_hard:
1792 vol->retry = 1;
1793 break;
1794 case Opt_soft:
1795 vol->retry = 0;
1796 break;
1797 case Opt_perm:
1798 vol->noperm = 0;
1799 break;
1800 case Opt_noperm:
1801 vol->noperm = 1;
1802 break;
1803 case Opt_mapchars:
1804 vol->sfu_remap = true;
1805 vol->remap = false; /* disable SFM mapping */
1806 break;
1807 case Opt_nomapchars:
1808 vol->sfu_remap = false;
1809 break;
1810 case Opt_mapposix:
1811 vol->remap = true;
1812 vol->sfu_remap = false; /* disable SFU mapping */
1813 break;
1814 case Opt_nomapposix:
1815 vol->remap = false;
1816 break;
1817 case Opt_sfu:
1818 vol->sfu_emul = 1;
1819 break;
1820 case Opt_nosfu:
1821 vol->sfu_emul = 0;
1822 break;
1823 case Opt_nodfs:
1824 vol->nodfs = 1;
1825 break;
David Brazdil0f672f62019-12-10 10:32:29 +00001826 case Opt_rootfs:
1827#ifdef CONFIG_CIFS_ROOT
1828 vol->rootfs = true;
1829#endif
1830 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001831 case Opt_posixpaths:
1832 vol->posix_paths = 1;
1833 break;
1834 case Opt_noposixpaths:
1835 vol->posix_paths = 0;
1836 break;
1837 case Opt_nounix:
1838 if (vol->linux_ext)
1839 cifs_dbg(VFS,
1840 "conflicting unix mount options\n");
1841 vol->no_linux_ext = 1;
1842 break;
1843 case Opt_unix:
1844 if (vol->no_linux_ext)
1845 cifs_dbg(VFS,
1846 "conflicting unix mount options\n");
1847 vol->linux_ext = 1;
1848 break;
1849 case Opt_nocase:
1850 vol->nocase = 1;
1851 break;
1852 case Opt_brl:
1853 vol->nobrl = 0;
1854 break;
1855 case Opt_nobrl:
1856 vol->nobrl = 1;
1857 /*
1858 * turn off mandatory locking in mode
1859 * if remote locking is turned off since the
1860 * local vfs will do advisory
1861 */
1862 if (vol->file_mode ==
1863 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1864 vol->file_mode = S_IALLUGO;
1865 break;
1866 case Opt_nohandlecache:
1867 vol->nohandlecache = 1;
1868 break;
1869 case Opt_handlecache:
1870 vol->nohandlecache = 0;
1871 break;
1872 case Opt_forcemandatorylock:
1873 vol->mand_lock = 1;
1874 break;
1875 case Opt_setuids:
1876 vol->setuids = 1;
1877 break;
1878 case Opt_nosetuids:
1879 vol->setuids = 0;
1880 break;
1881 case Opt_setuidfromacl:
1882 vol->setuidfromacl = 1;
1883 break;
1884 case Opt_dynperm:
1885 vol->dynperm = true;
1886 break;
1887 case Opt_nodynperm:
1888 vol->dynperm = false;
1889 break;
1890 case Opt_nohard:
1891 vol->retry = 0;
1892 break;
1893 case Opt_nosoft:
1894 vol->retry = 1;
1895 break;
1896 case Opt_nointr:
1897 vol->intr = 0;
1898 break;
1899 case Opt_intr:
1900 vol->intr = 1;
1901 break;
1902 case Opt_nostrictsync:
1903 vol->nostrictsync = 1;
1904 break;
1905 case Opt_strictsync:
1906 vol->nostrictsync = 0;
1907 break;
1908 case Opt_serverino:
1909 vol->server_ino = 1;
1910 break;
1911 case Opt_noserverino:
1912 vol->server_ino = 0;
1913 break;
1914 case Opt_rwpidforward:
1915 vol->rwpidforward = 1;
1916 break;
David Brazdil0f672f62019-12-10 10:32:29 +00001917 case Opt_modesid:
1918 vol->mode_ace = 1;
1919 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001920 case Opt_cifsacl:
1921 vol->cifs_acl = 1;
1922 break;
1923 case Opt_nocifsacl:
1924 vol->cifs_acl = 0;
1925 break;
1926 case Opt_acl:
1927 vol->no_psx_acl = 0;
1928 break;
1929 case Opt_noacl:
1930 vol->no_psx_acl = 1;
1931 break;
1932 case Opt_locallease:
1933 vol->local_lease = 1;
1934 break;
1935 case Opt_sign:
1936 vol->sign = true;
1937 break;
David Brazdil0f672f62019-12-10 10:32:29 +00001938 case Opt_ignore_signature:
1939 vol->sign = true;
1940 vol->ignore_signature = true;
1941 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001942 case Opt_seal:
1943 /* we do not do the following in secFlags because seal
1944 * is a per tree connection (mount) not a per socket
1945 * or per-smb connection option in the protocol
1946 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1947 */
1948 vol->seal = 1;
1949 break;
1950 case Opt_noac:
1951 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1952 break;
1953 case Opt_fsc:
1954#ifndef CONFIG_CIFS_FSCACHE
1955 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
1956 goto cifs_parse_mount_err;
1957#endif
1958 vol->fsc = true;
1959 break;
1960 case Opt_mfsymlinks:
1961 vol->mfsymlinks = true;
1962 break;
1963 case Opt_multiuser:
1964 vol->multiuser = true;
1965 break;
1966 case Opt_sloppy:
1967 sloppy = true;
1968 break;
1969 case Opt_nosharesock:
1970 vol->nosharesock = true;
1971 break;
1972 case Opt_nopersistent:
1973 vol->nopersistent = true;
1974 if (vol->persistent) {
1975 cifs_dbg(VFS,
1976 "persistenthandles mount options conflict\n");
1977 goto cifs_parse_mount_err;
1978 }
1979 break;
1980 case Opt_persistent:
1981 vol->persistent = true;
1982 if ((vol->nopersistent) || (vol->resilient)) {
1983 cifs_dbg(VFS,
1984 "persistenthandles mount options conflict\n");
1985 goto cifs_parse_mount_err;
1986 }
1987 break;
1988 case Opt_resilient:
1989 vol->resilient = true;
1990 if (vol->persistent) {
1991 cifs_dbg(VFS,
1992 "persistenthandles mount options conflict\n");
1993 goto cifs_parse_mount_err;
1994 }
1995 break;
1996 case Opt_noresilient:
1997 vol->resilient = false; /* already the default */
1998 break;
1999 case Opt_domainauto:
2000 vol->domainauto = true;
2001 break;
2002 case Opt_rdma:
2003 vol->rdma = true;
2004 break;
David Brazdil0f672f62019-12-10 10:32:29 +00002005 case Opt_compress:
2006 vol->compression = UNKNOWN_TYPE;
2007 cifs_dbg(VFS,
2008 "SMB3 compression support is experimental\n");
2009 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002010
2011 /* Numeric Values */
2012 case Opt_backupuid:
2013 if (get_option_uid(args, &vol->backupuid)) {
2014 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
2015 __func__);
2016 goto cifs_parse_mount_err;
2017 }
2018 vol->backupuid_specified = true;
2019 break;
2020 case Opt_backupgid:
2021 if (get_option_gid(args, &vol->backupgid)) {
2022 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
2023 __func__);
2024 goto cifs_parse_mount_err;
2025 }
2026 vol->backupgid_specified = true;
2027 break;
2028 case Opt_uid:
2029 if (get_option_uid(args, &vol->linux_uid)) {
2030 cifs_dbg(VFS, "%s: Invalid uid value\n",
2031 __func__);
2032 goto cifs_parse_mount_err;
2033 }
2034 uid_specified = true;
2035 break;
2036 case Opt_cruid:
2037 if (get_option_uid(args, &vol->cred_uid)) {
2038 cifs_dbg(VFS, "%s: Invalid cruid value\n",
2039 __func__);
2040 goto cifs_parse_mount_err;
2041 }
2042 break;
2043 case Opt_gid:
2044 if (get_option_gid(args, &vol->linux_gid)) {
2045 cifs_dbg(VFS, "%s: Invalid gid value\n",
2046 __func__);
2047 goto cifs_parse_mount_err;
2048 }
2049 gid_specified = true;
2050 break;
2051 case Opt_file_mode:
2052 if (get_option_ul(args, &option)) {
2053 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
2054 __func__);
2055 goto cifs_parse_mount_err;
2056 }
2057 vol->file_mode = option;
2058 break;
2059 case Opt_dirmode:
2060 if (get_option_ul(args, &option)) {
2061 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
2062 __func__);
2063 goto cifs_parse_mount_err;
2064 }
2065 vol->dir_mode = option;
2066 break;
2067 case Opt_port:
2068 if (get_option_ul(args, &option) ||
2069 option > USHRT_MAX) {
2070 cifs_dbg(VFS, "%s: Invalid port value\n",
2071 __func__);
2072 goto cifs_parse_mount_err;
2073 }
2074 port = (unsigned short)option;
2075 break;
David Brazdil0f672f62019-12-10 10:32:29 +00002076 case Opt_min_enc_offload:
2077 if (get_option_ul(args, &option)) {
2078 cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
2079 goto cifs_parse_mount_err;
2080 }
2081 vol->min_offload = option;
2082 break;
2083 case Opt_blocksize:
2084 if (get_option_ul(args, &option)) {
2085 cifs_dbg(VFS, "%s: Invalid blocksize value\n",
2086 __func__);
2087 goto cifs_parse_mount_err;
2088 }
2089 /*
2090 * inode blocksize realistically should never need to be
2091 * less than 16K or greater than 16M and default is 1MB.
2092 * Note that small inode block sizes (e.g. 64K) can lead
2093 * to very poor performance of common tools like cp and scp
2094 */
2095 if ((option < CIFS_MAX_MSGSIZE) ||
2096 (option > (4 * SMB3_DEFAULT_IOSIZE))) {
2097 cifs_dbg(VFS, "%s: Invalid blocksize\n",
2098 __func__);
2099 goto cifs_parse_mount_err;
2100 }
2101 vol->bsize = option;
2102 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002103 case Opt_rsize:
2104 if (get_option_ul(args, &option)) {
2105 cifs_dbg(VFS, "%s: Invalid rsize value\n",
2106 __func__);
2107 goto cifs_parse_mount_err;
2108 }
2109 vol->rsize = option;
2110 break;
2111 case Opt_wsize:
2112 if (get_option_ul(args, &option)) {
2113 cifs_dbg(VFS, "%s: Invalid wsize value\n",
2114 __func__);
2115 goto cifs_parse_mount_err;
2116 }
2117 vol->wsize = option;
2118 break;
2119 case Opt_actimeo:
2120 if (get_option_ul(args, &option)) {
2121 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
2122 __func__);
2123 goto cifs_parse_mount_err;
2124 }
2125 vol->actimeo = HZ * option;
2126 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
2127 cifs_dbg(VFS, "attribute cache timeout too large\n");
2128 goto cifs_parse_mount_err;
2129 }
2130 break;
David Brazdil0f672f62019-12-10 10:32:29 +00002131 case Opt_handletimeout:
2132 if (get_option_ul(args, &option)) {
2133 cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
2134 __func__);
2135 goto cifs_parse_mount_err;
2136 }
2137 vol->handle_timeout = option;
2138 if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
2139 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
2140 goto cifs_parse_mount_err;
2141 }
2142 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002143 case Opt_echo_interval:
2144 if (get_option_ul(args, &option)) {
2145 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
2146 __func__);
2147 goto cifs_parse_mount_err;
2148 }
2149 vol->echo_interval = option;
2150 break;
2151 case Opt_snapshot:
2152 if (get_option_ul(args, &option)) {
2153 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
2154 __func__);
2155 goto cifs_parse_mount_err;
2156 }
2157 vol->snapshot_time = option;
2158 break;
2159 case Opt_max_credits:
2160 if (get_option_ul(args, &option) || (option < 20) ||
2161 (option > 60000)) {
2162 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
2163 __func__);
2164 goto cifs_parse_mount_err;
2165 }
2166 vol->max_credits = option;
2167 break;
2168
2169 /* String Arguments */
2170
2171 case Opt_blank_user:
2172 /* null user, ie. anonymous authentication */
2173 vol->nullauth = 1;
2174 vol->username = NULL;
2175 break;
2176 case Opt_user:
2177 string = match_strdup(args);
2178 if (string == NULL)
2179 goto out_nomem;
2180
2181 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
2182 CIFS_MAX_USERNAME_LEN) {
2183 pr_warn("CIFS: username too long\n");
2184 goto cifs_parse_mount_err;
2185 }
2186
2187 kfree(vol->username);
2188 vol->username = kstrdup(string, GFP_KERNEL);
2189 if (!vol->username)
2190 goto cifs_parse_mount_err;
2191 break;
2192 case Opt_blank_pass:
2193 /* passwords have to be handled differently
2194 * to allow the character used for deliminator
2195 * to be passed within them
2196 */
2197
2198 /*
2199 * Check if this is a case where the password
2200 * starts with a delimiter
2201 */
2202 tmp_end = strchr(data, '=');
2203 tmp_end++;
2204 if (!(tmp_end < end && tmp_end[1] == delim)) {
2205 /* No it is not. Set the password to NULL */
2206 kzfree(vol->password);
2207 vol->password = NULL;
2208 break;
2209 }
David Brazdil0f672f62019-12-10 10:32:29 +00002210 /* Fallthrough - to Opt_pass below.*/
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002211 case Opt_pass:
2212 /* Obtain the value string */
2213 value = strchr(data, '=');
2214 value++;
2215
2216 /* Set tmp_end to end of the string */
2217 tmp_end = (char *) value + strlen(value);
2218
2219 /* Check if following character is the deliminator
2220 * If yes, we have encountered a double deliminator
2221 * reset the NULL character to the deliminator
2222 */
2223 if (tmp_end < end && tmp_end[1] == delim) {
2224 tmp_end[0] = delim;
2225
2226 /* Keep iterating until we get to a single
2227 * deliminator OR the end
2228 */
2229 while ((tmp_end = strchr(tmp_end, delim))
2230 != NULL && (tmp_end[1] == delim)) {
2231 tmp_end = (char *) &tmp_end[2];
2232 }
2233
2234 /* Reset var options to point to next element */
2235 if (tmp_end) {
2236 tmp_end[0] = '\0';
2237 options = (char *) &tmp_end[1];
2238 } else
2239 /* Reached the end of the mount option
2240 * string */
2241 options = end;
2242 }
2243
2244 kzfree(vol->password);
2245 /* Now build new password string */
2246 temp_len = strlen(value);
2247 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2248 if (vol->password == NULL) {
2249 pr_warn("CIFS: no memory for password\n");
2250 goto cifs_parse_mount_err;
2251 }
2252
2253 for (i = 0, j = 0; i < temp_len; i++, j++) {
2254 vol->password[j] = value[i];
2255 if ((value[i] == delim) &&
2256 value[i+1] == delim)
2257 /* skip the second deliminator */
2258 i++;
2259 }
2260 vol->password[j] = '\0';
2261 break;
2262 case Opt_blank_ip:
2263 /* FIXME: should this be an error instead? */
2264 got_ip = false;
2265 break;
2266 case Opt_ip:
2267 string = match_strdup(args);
2268 if (string == NULL)
2269 goto out_nomem;
2270
2271 if (!cifs_convert_address(dstaddr, string,
2272 strlen(string))) {
2273 pr_err("CIFS: bad ip= option (%s).\n", string);
2274 goto cifs_parse_mount_err;
2275 }
2276 got_ip = true;
2277 break;
2278 case Opt_domain:
2279 string = match_strdup(args);
2280 if (string == NULL)
2281 goto out_nomem;
2282
2283 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2284 == CIFS_MAX_DOMAINNAME_LEN) {
2285 pr_warn("CIFS: domain name too long\n");
2286 goto cifs_parse_mount_err;
2287 }
2288
2289 kfree(vol->domainname);
2290 vol->domainname = kstrdup(string, GFP_KERNEL);
2291 if (!vol->domainname) {
2292 pr_warn("CIFS: no memory for domainname\n");
2293 goto cifs_parse_mount_err;
2294 }
2295 cifs_dbg(FYI, "Domain name set\n");
2296 break;
2297 case Opt_srcaddr:
2298 string = match_strdup(args);
2299 if (string == NULL)
2300 goto out_nomem;
2301
2302 if (!cifs_convert_address(
2303 (struct sockaddr *)&vol->srcaddr,
2304 string, strlen(string))) {
2305 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2306 string);
2307 goto cifs_parse_mount_err;
2308 }
2309 break;
2310 case Opt_iocharset:
2311 string = match_strdup(args);
2312 if (string == NULL)
2313 goto out_nomem;
2314
2315 if (strnlen(string, 1024) >= 65) {
2316 pr_warn("CIFS: iocharset name too long.\n");
2317 goto cifs_parse_mount_err;
2318 }
2319
2320 if (strncasecmp(string, "default", 7) != 0) {
2321 kfree(vol->iocharset);
2322 vol->iocharset = kstrdup(string,
2323 GFP_KERNEL);
2324 if (!vol->iocharset) {
2325 pr_warn("CIFS: no memory for charset\n");
2326 goto cifs_parse_mount_err;
2327 }
2328 }
2329 /* if iocharset not set then load_nls_default
2330 * is used by caller
2331 */
2332 cifs_dbg(FYI, "iocharset set to %s\n", string);
2333 break;
2334 case Opt_netbiosname:
2335 string = match_strdup(args);
2336 if (string == NULL)
2337 goto out_nomem;
2338
2339 memset(vol->source_rfc1001_name, 0x20,
2340 RFC1001_NAME_LEN);
2341 /*
2342 * FIXME: are there cases in which a comma can
2343 * be valid in workstation netbios name (and
2344 * need special handling)?
2345 */
2346 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2347 /* don't ucase netbiosname for user */
2348 if (string[i] == 0)
2349 break;
2350 vol->source_rfc1001_name[i] = string[i];
2351 }
2352 /* The string has 16th byte zero still from
2353 * set at top of the function
2354 */
2355 if (i == RFC1001_NAME_LEN && string[i] != 0)
2356 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
2357 break;
2358 case Opt_servern:
2359 /* servernetbiosname specified override *SMBSERVER */
2360 string = match_strdup(args);
2361 if (string == NULL)
2362 goto out_nomem;
2363
2364 /* last byte, type, is 0x20 for servr type */
2365 memset(vol->target_rfc1001_name, 0x20,
2366 RFC1001_NAME_LEN_WITH_NULL);
2367
2368 /* BB are there cases in which a comma can be
2369 valid in this workstation netbios name
2370 (and need special handling)? */
2371
2372 /* user or mount helper must uppercase the
2373 netbios name */
2374 for (i = 0; i < 15; i++) {
2375 if (string[i] == 0)
2376 break;
2377 vol->target_rfc1001_name[i] = string[i];
2378 }
2379 /* The string has 16th byte zero still from
2380 set at top of the function */
2381 if (i == RFC1001_NAME_LEN && string[i] != 0)
2382 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
2383 break;
2384 case Opt_ver:
2385 /* version of mount userspace tools, not dialect */
2386 string = match_strdup(args);
2387 if (string == NULL)
2388 goto out_nomem;
2389
2390 /* If interface changes in mount.cifs bump to new ver */
2391 if (strncasecmp(string, "1", 1) == 0) {
2392 if (strlen(string) > 1) {
2393 pr_warn("Bad mount helper ver=%s. Did "
2394 "you want SMB1 (CIFS) dialect "
2395 "and mean to type vers=1.0 "
2396 "instead?\n", string);
2397 goto cifs_parse_mount_err;
2398 }
2399 /* This is the default */
2400 break;
2401 }
2402 /* For all other value, error */
2403 pr_warn("CIFS: Invalid mount helper version specified\n");
2404 goto cifs_parse_mount_err;
2405 case Opt_vers:
2406 /* protocol version (dialect) */
2407 string = match_strdup(args);
2408 if (string == NULL)
2409 goto out_nomem;
2410
2411 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
2412 goto cifs_parse_mount_err;
2413 got_version = true;
2414 break;
2415 case Opt_sec:
2416 string = match_strdup(args);
2417 if (string == NULL)
2418 goto out_nomem;
2419
2420 if (cifs_parse_security_flavors(string, vol) != 0)
2421 goto cifs_parse_mount_err;
2422 break;
2423 case Opt_cache:
2424 string = match_strdup(args);
2425 if (string == NULL)
2426 goto out_nomem;
2427
2428 if (cifs_parse_cache_flavor(string, vol) != 0)
2429 goto cifs_parse_mount_err;
2430 break;
2431 default:
2432 /*
2433 * An option we don't recognize. Save it off for later
2434 * if we haven't already found one
2435 */
2436 if (!invalid)
2437 invalid = data;
2438 break;
2439 }
2440 /* Free up any allocated string */
2441 kfree(string);
2442 string = NULL;
2443 }
2444
2445 if (!sloppy && invalid) {
2446 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
2447 goto cifs_parse_mount_err;
2448 }
2449
2450 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2451 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2452 goto cifs_parse_mount_err;
2453 }
2454
2455#ifndef CONFIG_KEYS
2456 /* Muliuser mounts require CONFIG_KEYS support */
2457 if (vol->multiuser) {
2458 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
2459 goto cifs_parse_mount_err;
2460 }
2461#endif
2462 if (!vol->UNC) {
2463 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
2464 goto cifs_parse_mount_err;
2465 }
2466
2467 /* make sure UNC has a share name */
2468 if (!strchr(vol->UNC + 3, '\\')) {
2469 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
2470 goto cifs_parse_mount_err;
2471 }
2472
2473 if (!got_ip) {
2474 int len;
2475 const char *slash;
2476
2477 /* No ip= option specified? Try to get it from UNC */
2478 /* Use the address part of the UNC. */
2479 slash = strchr(&vol->UNC[2], '\\');
2480 len = slash - &vol->UNC[2];
2481 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
2482 pr_err("Unable to determine destination address.\n");
2483 goto cifs_parse_mount_err;
2484 }
2485 }
2486
2487 /* set the port that we got earlier */
2488 cifs_set_port(dstaddr, port);
2489
2490 if (uid_specified)
2491 vol->override_uid = override_uid;
2492 else if (override_uid == 1)
2493 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
2494
2495 if (gid_specified)
2496 vol->override_gid = override_gid;
2497 else if (override_gid == 1)
2498 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
2499
2500 if (got_version == false)
2501 pr_warn("No dialect specified on mount. Default has changed to "
2502 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
2503 "(SMB1). To use the less secure SMB1 dialect to access "
2504 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2505 " on mount.\n");
2506
2507 kfree(mountdata_copy);
2508 return 0;
2509
2510out_nomem:
2511 pr_warn("Could not allocate temporary buffer\n");
2512cifs_parse_mount_err:
2513 kfree(string);
2514 kfree(mountdata_copy);
2515 return 1;
2516}
2517
2518/** Returns true if srcaddr isn't specified and rhs isn't
2519 * specified, or if srcaddr is specified and
2520 * matches the IP address of the rhs argument.
2521 */
2522static bool
2523srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2524{
2525 switch (srcaddr->sa_family) {
2526 case AF_UNSPEC:
2527 return (rhs->sa_family == AF_UNSPEC);
2528 case AF_INET: {
2529 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2530 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2531 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2532 }
2533 case AF_INET6: {
2534 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
2535 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
2536 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2537 }
2538 default:
2539 WARN_ON(1);
2540 return false; /* don't expect to be here */
2541 }
2542}
2543
2544/*
2545 * If no port is specified in addr structure, we try to match with 445 port
2546 * and if it fails - with 139 ports. It should be called only if address
2547 * families of server and addr are equal.
2548 */
2549static bool
2550match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2551{
2552 __be16 port, *sport;
2553
David Brazdil0f672f62019-12-10 10:32:29 +00002554 /* SMBDirect manages its own ports, don't match it here */
2555 if (server->rdma)
2556 return true;
2557
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002558 switch (addr->sa_family) {
2559 case AF_INET:
2560 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2561 port = ((struct sockaddr_in *) addr)->sin_port;
2562 break;
2563 case AF_INET6:
2564 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2565 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2566 break;
2567 default:
2568 WARN_ON(1);
2569 return false;
2570 }
2571
2572 if (!port) {
2573 port = htons(CIFS_PORT);
2574 if (port == *sport)
2575 return true;
2576
2577 port = htons(RFC1001_PORT);
2578 }
2579
2580 return port == *sport;
2581}
2582
2583static bool
2584match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2585 struct sockaddr *srcaddr)
2586{
2587 switch (addr->sa_family) {
2588 case AF_INET: {
2589 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2590 struct sockaddr_in *srv_addr4 =
2591 (struct sockaddr_in *)&server->dstaddr;
2592
2593 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
2594 return false;
2595 break;
2596 }
2597 case AF_INET6: {
2598 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2599 struct sockaddr_in6 *srv_addr6 =
2600 (struct sockaddr_in6 *)&server->dstaddr;
2601
2602 if (!ipv6_addr_equal(&addr6->sin6_addr,
2603 &srv_addr6->sin6_addr))
2604 return false;
2605 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
2606 return false;
2607 break;
2608 }
2609 default:
2610 WARN_ON(1);
2611 return false; /* don't expect to be here */
2612 }
2613
2614 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2615 return false;
2616
2617 return true;
2618}
2619
2620static bool
2621match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2622{
2623 /*
2624 * The select_sectype function should either return the vol->sectype
2625 * that was specified, or "Unspecified" if that sectype was not
2626 * compatible with the given NEGOTIATE request.
2627 */
2628 if (server->ops->select_sectype(server, vol->sectype)
2629 == Unspecified)
2630 return false;
2631
2632 /*
2633 * Now check if signing mode is acceptable. No need to check
2634 * global_secflags at this point since if MUST_SIGN is set then
2635 * the server->sign had better be too.
2636 */
2637 if (vol->sign && !server->sign)
2638 return false;
2639
2640 return true;
2641}
2642
2643static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
2644{
2645 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2646
2647 if (vol->nosharesock)
2648 return 0;
2649
David Brazdil0f672f62019-12-10 10:32:29 +00002650 /* If multidialect negotiation see if existing sessions match one */
2651 if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2652 if (server->vals->protocol_id < SMB30_PROT_ID)
2653 return 0;
2654 } else if (strcmp(vol->vals->version_string,
2655 SMBDEFAULT_VERSION_STRING) == 0) {
2656 if (server->vals->protocol_id < SMB21_PROT_ID)
2657 return 0;
2658 } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002659 return 0;
2660
2661 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2662 return 0;
2663
2664 if (!match_address(server, addr,
2665 (struct sockaddr *)&vol->srcaddr))
2666 return 0;
2667
2668 if (!match_port(server, addr))
2669 return 0;
2670
2671 if (!match_security(server, vol))
2672 return 0;
2673
2674 if (server->echo_interval != vol->echo_interval * HZ)
2675 return 0;
2676
2677 if (server->rdma != vol->rdma)
2678 return 0;
2679
David Brazdil0f672f62019-12-10 10:32:29 +00002680 if (server->ignore_signature != vol->ignore_signature)
2681 return 0;
2682
2683 if (server->min_offload != vol->min_offload)
2684 return 0;
2685
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002686 return 1;
2687}
2688
David Brazdil0f672f62019-12-10 10:32:29 +00002689struct TCP_Server_Info *
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002690cifs_find_tcp_session(struct smb_vol *vol)
2691{
2692 struct TCP_Server_Info *server;
2693
2694 spin_lock(&cifs_tcp_ses_lock);
2695 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
2696 if (!match_server(server, vol))
2697 continue;
2698
2699 ++server->srv_count;
2700 spin_unlock(&cifs_tcp_ses_lock);
2701 cifs_dbg(FYI, "Existing tcp session with server found\n");
2702 return server;
2703 }
2704 spin_unlock(&cifs_tcp_ses_lock);
2705 return NULL;
2706}
2707
2708void
2709cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
2710{
2711 struct task_struct *task;
2712
2713 spin_lock(&cifs_tcp_ses_lock);
2714 if (--server->srv_count > 0) {
2715 spin_unlock(&cifs_tcp_ses_lock);
2716 return;
2717 }
2718
2719 put_net(cifs_net_ns(server));
2720
2721 list_del_init(&server->tcp_ses_list);
2722 spin_unlock(&cifs_tcp_ses_lock);
2723
2724 cancel_delayed_work_sync(&server->echo);
2725
2726 if (from_reconnect)
2727 /*
2728 * Avoid deadlock here: reconnect work calls
2729 * cifs_put_tcp_session() at its end. Need to be sure
2730 * that reconnect work does nothing with server pointer after
2731 * that step.
2732 */
2733 cancel_delayed_work(&server->reconnect);
2734 else
2735 cancel_delayed_work_sync(&server->reconnect);
2736
2737 spin_lock(&GlobalMid_Lock);
2738 server->tcpStatus = CifsExiting;
2739 spin_unlock(&GlobalMid_Lock);
2740
2741 cifs_crypto_secmech_release(server);
2742 cifs_fscache_release_client_cookie(server);
2743
2744 kfree(server->session_key.response);
2745 server->session_key.response = NULL;
2746 server->session_key.len = 0;
2747
2748 task = xchg(&server->tsk, NULL);
2749 if (task)
David Brazdil0f672f62019-12-10 10:32:29 +00002750 send_sig(SIGKILL, task, 1);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002751}
2752
2753static struct TCP_Server_Info *
2754cifs_get_tcp_session(struct smb_vol *volume_info)
2755{
2756 struct TCP_Server_Info *tcp_ses = NULL;
2757 int rc;
2758
2759 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
2760
2761 /* see if we already have a matching tcp_ses */
2762 tcp_ses = cifs_find_tcp_session(volume_info);
2763 if (tcp_ses)
2764 return tcp_ses;
2765
2766 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2767 if (!tcp_ses) {
2768 rc = -ENOMEM;
2769 goto out_err;
2770 }
2771
2772 tcp_ses->ops = volume_info->ops;
2773 tcp_ses->vals = volume_info->vals;
2774 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
2775 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2776 if (IS_ERR(tcp_ses->hostname)) {
2777 rc = PTR_ERR(tcp_ses->hostname);
2778 goto out_err_crypto_release;
2779 }
2780
David Brazdil0f672f62019-12-10 10:32:29 +00002781 tcp_ses->noblockcnt = volume_info->rootfs;
2782 tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002783 tcp_ses->noautotune = volume_info->noautotune;
2784 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
2785 tcp_ses->rdma = volume_info->rdma;
2786 tcp_ses->in_flight = 0;
David Brazdil0f672f62019-12-10 10:32:29 +00002787 tcp_ses->max_in_flight = 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002788 tcp_ses->credits = 1;
2789 init_waitqueue_head(&tcp_ses->response_q);
2790 init_waitqueue_head(&tcp_ses->request_q);
2791 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2792 mutex_init(&tcp_ses->srv_mutex);
2793 memcpy(tcp_ses->workstation_RFC1001_name,
2794 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2795 memcpy(tcp_ses->server_RFC1001_name,
2796 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2797 tcp_ses->session_estab = false;
2798 tcp_ses->sequence_number = 0;
David Brazdil0f672f62019-12-10 10:32:29 +00002799 tcp_ses->reconnect_instance = 1;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002800 tcp_ses->lstrp = jiffies;
David Brazdil0f672f62019-12-10 10:32:29 +00002801 tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002802 spin_lock_init(&tcp_ses->req_lock);
2803 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2804 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
2805 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
2806 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2807 mutex_init(&tcp_ses->reconnect_mutex);
2808 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2809 sizeof(tcp_ses->srcaddr));
2810 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2811 sizeof(tcp_ses->dstaddr));
2812 generate_random_uuid(tcp_ses->client_guid);
2813 /*
2814 * at this point we are the only ones with the pointer
2815 * to the struct since the kernel thread not created yet
2816 * no need to spinlock this init of tcpStatus or srv_count
2817 */
2818 tcp_ses->tcpStatus = CifsNew;
2819 ++tcp_ses->srv_count;
2820
2821 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2822 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2823 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2824 else
2825 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
2826 if (tcp_ses->rdma) {
2827#ifndef CONFIG_CIFS_SMB_DIRECT
2828 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2829 rc = -ENOENT;
2830 goto out_err_crypto_release;
2831#endif
2832 tcp_ses->smbd_conn = smbd_get_connection(
2833 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2834 if (tcp_ses->smbd_conn) {
2835 cifs_dbg(VFS, "RDMA transport established\n");
2836 rc = 0;
2837 goto smbd_connected;
2838 } else {
2839 rc = -ENOENT;
2840 goto out_err_crypto_release;
2841 }
2842 }
2843 rc = ip_connect(tcp_ses);
2844 if (rc < 0) {
2845 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
2846 goto out_err_crypto_release;
2847 }
2848smbd_connected:
2849 /*
2850 * since we're in a cifs function already, we know that
2851 * this will succeed. No need for try_module_get().
2852 */
2853 __module_get(THIS_MODULE);
2854 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
2855 tcp_ses, "cifsd");
2856 if (IS_ERR(tcp_ses->tsk)) {
2857 rc = PTR_ERR(tcp_ses->tsk);
2858 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
2859 module_put(THIS_MODULE);
2860 goto out_err_crypto_release;
2861 }
David Brazdil0f672f62019-12-10 10:32:29 +00002862 tcp_ses->min_offload = volume_info->min_offload;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002863 tcp_ses->tcpStatus = CifsNeedNegotiate;
2864
David Brazdil0f672f62019-12-10 10:32:29 +00002865 tcp_ses->nr_targets = 1;
2866 tcp_ses->ignore_signature = volume_info->ignore_signature;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002867 /* thread spawned, put it on the list */
2868 spin_lock(&cifs_tcp_ses_lock);
2869 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
2870 spin_unlock(&cifs_tcp_ses_lock);
2871
2872 cifs_fscache_get_client_cookie(tcp_ses);
2873
2874 /* queue echo request delayed work */
2875 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
2876
2877 return tcp_ses;
2878
2879out_err_crypto_release:
2880 cifs_crypto_secmech_release(tcp_ses);
2881
2882 put_net(cifs_net_ns(tcp_ses));
2883
2884out_err:
2885 if (tcp_ses) {
2886 if (!IS_ERR(tcp_ses->hostname))
2887 kfree(tcp_ses->hostname);
2888 if (tcp_ses->ssocket)
2889 sock_release(tcp_ses->ssocket);
2890 kfree(tcp_ses);
2891 }
2892 return ERR_PTR(rc);
2893}
2894
2895static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
2896{
2897 if (vol->sectype != Unspecified &&
2898 vol->sectype != ses->sectype)
2899 return 0;
2900
2901 switch (ses->sectype) {
2902 case Kerberos:
2903 if (!uid_eq(vol->cred_uid, ses->cred_uid))
2904 return 0;
2905 break;
2906 default:
2907 /* NULL username means anonymous session */
2908 if (ses->user_name == NULL) {
2909 if (!vol->nullauth)
2910 return 0;
2911 break;
2912 }
2913
2914 /* anything else takes username/password */
2915 if (strncmp(ses->user_name,
2916 vol->username ? vol->username : "",
2917 CIFS_MAX_USERNAME_LEN))
2918 return 0;
2919 if ((vol->username && strlen(vol->username) != 0) &&
2920 ses->password != NULL &&
2921 strncmp(ses->password,
2922 vol->password ? vol->password : "",
2923 CIFS_MAX_PASSWORD_LEN))
2924 return 0;
2925 }
2926 return 1;
2927}
2928
2929/**
2930 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2931 *
2932 * A new IPC connection is made and stored in the session
2933 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2934 */
2935static int
2936cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2937{
2938 int rc = 0, xid;
2939 struct cifs_tcon *tcon;
2940 struct nls_table *nls_codepage;
2941 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2942 bool seal = false;
David Brazdil0f672f62019-12-10 10:32:29 +00002943 struct TCP_Server_Info *server = ses->server;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002944
2945 /*
2946 * If the mount request that resulted in the creation of the
2947 * session requires encryption, force IPC to be encrypted too.
2948 */
2949 if (volume_info->seal) {
David Brazdil0f672f62019-12-10 10:32:29 +00002950 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002951 seal = true;
2952 else {
David Brazdil0f672f62019-12-10 10:32:29 +00002953 cifs_server_dbg(VFS,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002954 "IPC: server doesn't support encryption\n");
2955 return -EOPNOTSUPP;
2956 }
2957 }
2958
2959 tcon = tconInfoAlloc();
2960 if (tcon == NULL)
2961 return -ENOMEM;
2962
David Brazdil0f672f62019-12-10 10:32:29 +00002963 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002964
2965 /* cannot fail */
2966 nls_codepage = load_nls_default();
2967
2968 xid = get_xid();
2969 tcon->ses = ses;
2970 tcon->ipc = true;
2971 tcon->seal = seal;
David Brazdil0f672f62019-12-10 10:32:29 +00002972 rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002973 free_xid(xid);
2974
2975 if (rc) {
David Brazdil0f672f62019-12-10 10:32:29 +00002976 cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002977 tconInfoFree(tcon);
2978 goto out;
2979 }
2980
2981 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2982
2983 ses->tcon_ipc = tcon;
2984out:
2985 unload_nls(nls_codepage);
2986 return rc;
2987}
2988
2989/**
2990 * cifs_free_ipc - helper to release the session IPC tcon
2991 *
2992 * Needs to be called everytime a session is destroyed
2993 */
2994static int
2995cifs_free_ipc(struct cifs_ses *ses)
2996{
2997 int rc = 0, xid;
2998 struct cifs_tcon *tcon = ses->tcon_ipc;
2999
3000 if (tcon == NULL)
3001 return 0;
3002
3003 if (ses->server->ops->tree_disconnect) {
3004 xid = get_xid();
3005 rc = ses->server->ops->tree_disconnect(xid, tcon);
3006 free_xid(xid);
3007 }
3008
3009 if (rc)
3010 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
3011
3012 tconInfoFree(tcon);
3013 ses->tcon_ipc = NULL;
3014 return rc;
3015}
3016
3017static struct cifs_ses *
3018cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
3019{
3020 struct cifs_ses *ses;
3021
3022 spin_lock(&cifs_tcp_ses_lock);
3023 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
3024 if (ses->status == CifsExiting)
3025 continue;
3026 if (!match_session(ses, vol))
3027 continue;
3028 ++ses->ses_count;
3029 spin_unlock(&cifs_tcp_ses_lock);
3030 return ses;
3031 }
3032 spin_unlock(&cifs_tcp_ses_lock);
3033 return NULL;
3034}
3035
David Brazdil0f672f62019-12-10 10:32:29 +00003036void cifs_put_smb_ses(struct cifs_ses *ses)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003037{
3038 unsigned int rc, xid;
3039 struct TCP_Server_Info *server = ses->server;
3040
3041 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
3042
3043 spin_lock(&cifs_tcp_ses_lock);
3044 if (ses->status == CifsExiting) {
3045 spin_unlock(&cifs_tcp_ses_lock);
3046 return;
3047 }
3048 if (--ses->ses_count > 0) {
3049 spin_unlock(&cifs_tcp_ses_lock);
3050 return;
3051 }
Olivier Deprez0e641232021-09-23 10:07:05 +02003052 spin_unlock(&cifs_tcp_ses_lock);
3053
3054 spin_lock(&GlobalMid_Lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003055 if (ses->status == CifsGood)
3056 ses->status = CifsExiting;
Olivier Deprez0e641232021-09-23 10:07:05 +02003057 spin_unlock(&GlobalMid_Lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003058
3059 cifs_free_ipc(ses);
3060
3061 if (ses->status == CifsExiting && server->ops->logoff) {
3062 xid = get_xid();
3063 rc = server->ops->logoff(xid, ses);
3064 if (rc)
David Brazdil0f672f62019-12-10 10:32:29 +00003065 cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003066 __func__, rc);
3067 _free_xid(xid);
3068 }
3069
3070 spin_lock(&cifs_tcp_ses_lock);
3071 list_del_init(&ses->smb_ses_list);
3072 spin_unlock(&cifs_tcp_ses_lock);
3073
3074 sesInfoFree(ses);
3075 cifs_put_tcp_session(server, 0);
3076}
3077
3078#ifdef CONFIG_KEYS
3079
3080/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
3081#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
3082
3083/* Populate username and pw fields from keyring if possible */
3084static int
3085cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
3086{
3087 int rc = 0;
David Brazdil0f672f62019-12-10 10:32:29 +00003088 int is_domain = 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003089 const char *delim, *payload;
3090 char *desc;
3091 ssize_t len;
3092 struct key *key;
3093 struct TCP_Server_Info *server = ses->server;
3094 struct sockaddr_in *sa;
3095 struct sockaddr_in6 *sa6;
3096 const struct user_key_payload *upayload;
3097
3098 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
3099 if (!desc)
3100 return -ENOMEM;
3101
3102 /* try to find an address key first */
3103 switch (server->dstaddr.ss_family) {
3104 case AF_INET:
3105 sa = (struct sockaddr_in *)&server->dstaddr;
3106 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
3107 break;
3108 case AF_INET6:
3109 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
3110 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
3111 break;
3112 default:
3113 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
3114 server->dstaddr.ss_family);
3115 rc = -EINVAL;
3116 goto out_err;
3117 }
3118
3119 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
3120 key = request_key(&key_type_logon, desc, "");
3121 if (IS_ERR(key)) {
3122 if (!ses->domainName) {
3123 cifs_dbg(FYI, "domainName is NULL\n");
3124 rc = PTR_ERR(key);
3125 goto out_err;
3126 }
3127
3128 /* didn't work, try to find a domain key */
3129 sprintf(desc, "cifs:d:%s", ses->domainName);
3130 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
3131 key = request_key(&key_type_logon, desc, "");
3132 if (IS_ERR(key)) {
3133 rc = PTR_ERR(key);
3134 goto out_err;
3135 }
David Brazdil0f672f62019-12-10 10:32:29 +00003136 is_domain = 1;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003137 }
3138
3139 down_read(&key->sem);
3140 upayload = user_key_payload_locked(key);
3141 if (IS_ERR_OR_NULL(upayload)) {
3142 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
3143 goto out_key_put;
3144 }
3145
3146 /* find first : in payload */
3147 payload = upayload->data;
3148 delim = strnchr(payload, upayload->datalen, ':');
3149 cifs_dbg(FYI, "payload=%s\n", payload);
3150 if (!delim) {
3151 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
3152 upayload->datalen);
3153 rc = -EINVAL;
3154 goto out_key_put;
3155 }
3156
3157 len = delim - payload;
3158 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
3159 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
3160 len);
3161 rc = -EINVAL;
3162 goto out_key_put;
3163 }
3164
3165 vol->username = kstrndup(payload, len, GFP_KERNEL);
3166 if (!vol->username) {
3167 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
3168 len);
3169 rc = -ENOMEM;
3170 goto out_key_put;
3171 }
3172 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
3173
3174 len = key->datalen - (len + 1);
3175 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
3176 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
3177 rc = -EINVAL;
3178 kfree(vol->username);
3179 vol->username = NULL;
3180 goto out_key_put;
3181 }
3182
3183 ++delim;
3184 vol->password = kstrndup(delim, len, GFP_KERNEL);
3185 if (!vol->password) {
3186 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
3187 len);
3188 rc = -ENOMEM;
3189 kfree(vol->username);
3190 vol->username = NULL;
3191 goto out_key_put;
3192 }
3193
David Brazdil0f672f62019-12-10 10:32:29 +00003194 /*
3195 * If we have a domain key then we must set the domainName in the
3196 * for the request.
3197 */
3198 if (is_domain && ses->domainName) {
3199 vol->domainname = kstrndup(ses->domainName,
3200 strlen(ses->domainName),
3201 GFP_KERNEL);
3202 if (!vol->domainname) {
3203 cifs_dbg(FYI, "Unable to allocate %zd bytes for "
3204 "domain\n", len);
3205 rc = -ENOMEM;
3206 kfree(vol->username);
3207 vol->username = NULL;
3208 kzfree(vol->password);
3209 vol->password = NULL;
3210 goto out_key_put;
3211 }
3212 }
3213
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003214out_key_put:
3215 up_read(&key->sem);
3216 key_put(key);
3217out_err:
3218 kfree(desc);
3219 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
3220 return rc;
3221}
3222#else /* ! CONFIG_KEYS */
3223static inline int
3224cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
3225 struct cifs_ses *ses __attribute__((unused)))
3226{
3227 return -ENOSYS;
3228}
3229#endif /* CONFIG_KEYS */
3230
3231/**
3232 * cifs_get_smb_ses - get a session matching @volume_info data from @server
3233 *
3234 * This function assumes it is being called from cifs_mount() where we
3235 * already got a server reference (server refcount +1). See
3236 * cifs_get_tcon() for refcount explanations.
3237 */
David Brazdil0f672f62019-12-10 10:32:29 +00003238struct cifs_ses *
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003239cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3240{
3241 int rc = -ENOMEM;
3242 unsigned int xid;
3243 struct cifs_ses *ses;
3244 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3245 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3246
3247 xid = get_xid();
3248
3249 ses = cifs_find_smb_ses(server, volume_info);
3250 if (ses) {
3251 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3252 ses->status);
3253
3254 mutex_lock(&ses->session_mutex);
3255 rc = cifs_negotiate_protocol(xid, ses);
3256 if (rc) {
3257 mutex_unlock(&ses->session_mutex);
3258 /* problem -- put our ses reference */
3259 cifs_put_smb_ses(ses);
3260 free_xid(xid);
3261 return ERR_PTR(rc);
3262 }
3263 if (ses->need_reconnect) {
3264 cifs_dbg(FYI, "Session needs reconnect\n");
3265 rc = cifs_setup_session(xid, ses,
3266 volume_info->local_nls);
3267 if (rc) {
3268 mutex_unlock(&ses->session_mutex);
3269 /* problem -- put our reference */
3270 cifs_put_smb_ses(ses);
3271 free_xid(xid);
3272 return ERR_PTR(rc);
3273 }
3274 }
3275 mutex_unlock(&ses->session_mutex);
3276
3277 /* existing SMB ses has a server reference already */
3278 cifs_put_tcp_session(server, 0);
3279 free_xid(xid);
3280 return ses;
3281 }
3282
3283 cifs_dbg(FYI, "Existing smb sess not found\n");
3284 ses = sesInfoAlloc();
3285 if (ses == NULL)
3286 goto get_ses_fail;
3287
3288 /* new SMB session uses our server ref */
3289 ses->server = server;
3290 if (server->dstaddr.ss_family == AF_INET6)
3291 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
3292 else
3293 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
3294
3295 if (volume_info->username) {
3296 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3297 if (!ses->user_name)
3298 goto get_ses_fail;
3299 }
3300
3301 /* volume_info->password freed at unmount */
3302 if (volume_info->password) {
3303 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3304 if (!ses->password)
3305 goto get_ses_fail;
3306 }
3307 if (volume_info->domainname) {
3308 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3309 if (!ses->domainName)
3310 goto get_ses_fail;
3311 }
3312 if (volume_info->domainauto)
3313 ses->domainAuto = volume_info->domainauto;
3314 ses->cred_uid = volume_info->cred_uid;
3315 ses->linux_uid = volume_info->linux_uid;
3316
3317 ses->sectype = volume_info->sectype;
3318 ses->sign = volume_info->sign;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003319 mutex_lock(&ses->session_mutex);
3320 rc = cifs_negotiate_protocol(xid, ses);
3321 if (!rc)
3322 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
3323 mutex_unlock(&ses->session_mutex);
3324 if (rc)
3325 goto get_ses_fail;
3326
3327 /* success, put it on the list */
3328 spin_lock(&cifs_tcp_ses_lock);
3329 list_add(&ses->smb_ses_list, &server->smb_ses_list);
3330 spin_unlock(&cifs_tcp_ses_lock);
3331
3332 free_xid(xid);
3333
3334 cifs_setup_ipc(ses, volume_info);
3335
3336 return ses;
3337
3338get_ses_fail:
3339 sesInfoFree(ses);
3340 free_xid(xid);
3341 return ERR_PTR(rc);
3342}
3343
3344static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
3345{
3346 if (tcon->tidStatus == CifsExiting)
3347 return 0;
3348 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
3349 return 0;
3350 if (tcon->seal != volume_info->seal)
3351 return 0;
3352 if (tcon->snapshot_time != volume_info->snapshot_time)
3353 return 0;
David Brazdil0f672f62019-12-10 10:32:29 +00003354 if (tcon->handle_timeout != volume_info->handle_timeout)
3355 return 0;
3356 if (tcon->no_lease != volume_info->no_lease)
3357 return 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003358 return 1;
3359}
3360
3361static struct cifs_tcon *
3362cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
3363{
3364 struct list_head *tmp;
3365 struct cifs_tcon *tcon;
3366
3367 spin_lock(&cifs_tcp_ses_lock);
3368 list_for_each(tmp, &ses->tcon_list) {
3369 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Olivier Deprez0e641232021-09-23 10:07:05 +02003370#ifdef CONFIG_CIFS_DFS_UPCALL
3371 if (tcon->dfs_path)
3372 continue;
3373#endif
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003374 if (!match_tcon(tcon, volume_info))
3375 continue;
3376 ++tcon->tc_count;
3377 spin_unlock(&cifs_tcp_ses_lock);
3378 return tcon;
3379 }
3380 spin_unlock(&cifs_tcp_ses_lock);
3381 return NULL;
3382}
3383
3384void
3385cifs_put_tcon(struct cifs_tcon *tcon)
3386{
3387 unsigned int xid;
3388 struct cifs_ses *ses;
3389
3390 /*
3391 * IPC tcon share the lifetime of their session and are
3392 * destroyed in the session put function
3393 */
3394 if (tcon == NULL || tcon->ipc)
3395 return;
3396
3397 ses = tcon->ses;
3398 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
3399 spin_lock(&cifs_tcp_ses_lock);
3400 if (--tcon->tc_count > 0) {
3401 spin_unlock(&cifs_tcp_ses_lock);
3402 return;
3403 }
3404
3405 list_del_init(&tcon->tcon_list);
3406 spin_unlock(&cifs_tcp_ses_lock);
3407
3408 xid = get_xid();
3409 if (ses->server->ops->tree_disconnect)
3410 ses->server->ops->tree_disconnect(xid, tcon);
3411 _free_xid(xid);
3412
3413 cifs_fscache_release_super_cookie(tcon);
3414 tconInfoFree(tcon);
3415 cifs_put_smb_ses(ses);
3416}
3417
3418/**
3419 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3420 *
3421 * - tcon refcount is the number of mount points using the tcon.
3422 * - ses refcount is the number of tcon using the session.
3423 *
3424 * 1. This function assumes it is being called from cifs_mount() where
3425 * we already got a session reference (ses refcount +1).
3426 *
3427 * 2. Since we're in the context of adding a mount point, the end
3428 * result should be either:
3429 *
3430 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3431 * its session refcount incremented (1 new tcon). This +1 was
3432 * already done in (1).
3433 *
3434 * b) an existing tcon with refcount+1 (add a mount point to it) and
3435 * identical ses refcount (no new tcon). Because of (1) we need to
3436 * decrement the ses refcount.
3437 */
3438static struct cifs_tcon *
3439cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
3440{
3441 int rc, xid;
3442 struct cifs_tcon *tcon;
3443
3444 tcon = cifs_find_tcon(ses, volume_info);
3445 if (tcon) {
3446 /*
3447 * tcon has refcount already incremented but we need to
3448 * decrement extra ses reference gotten by caller (case b)
3449 */
3450 cifs_dbg(FYI, "Found match on UNC path\n");
3451 cifs_put_smb_ses(ses);
3452 return tcon;
3453 }
3454
3455 if (!ses->server->ops->tree_connect) {
3456 rc = -ENOSYS;
3457 goto out_fail;
3458 }
3459
3460 tcon = tconInfoAlloc();
3461 if (tcon == NULL) {
3462 rc = -ENOMEM;
3463 goto out_fail;
3464 }
3465
3466 if (volume_info->snapshot_time) {
3467 if (ses->server->vals->protocol_id == 0) {
3468 cifs_dbg(VFS,
3469 "Use SMB2 or later for snapshot mount option\n");
3470 rc = -EOPNOTSUPP;
3471 goto out_fail;
3472 } else
3473 tcon->snapshot_time = volume_info->snapshot_time;
3474 }
3475
David Brazdil0f672f62019-12-10 10:32:29 +00003476 if (volume_info->handle_timeout) {
3477 if (ses->server->vals->protocol_id == 0) {
3478 cifs_dbg(VFS,
3479 "Use SMB2.1 or later for handle timeout option\n");
3480 rc = -EOPNOTSUPP;
3481 goto out_fail;
3482 } else
3483 tcon->handle_timeout = volume_info->handle_timeout;
3484 }
3485
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003486 tcon->ses = ses;
3487 if (volume_info->password) {
3488 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3489 if (!tcon->password) {
3490 rc = -ENOMEM;
3491 goto out_fail;
3492 }
3493 }
3494
3495 if (volume_info->seal) {
3496 if (ses->server->vals->protocol_id == 0) {
3497 cifs_dbg(VFS,
3498 "SMB3 or later required for encryption\n");
3499 rc = -EOPNOTSUPP;
3500 goto out_fail;
3501 } else if (tcon->ses->server->capabilities &
3502 SMB2_GLOBAL_CAP_ENCRYPTION)
3503 tcon->seal = true;
3504 else {
3505 cifs_dbg(VFS, "Encryption is not supported on share\n");
3506 rc = -EOPNOTSUPP;
3507 goto out_fail;
3508 }
3509 }
3510
3511 if (volume_info->linux_ext) {
3512 if (ses->server->posix_ext_supported) {
3513 tcon->posix_extensions = true;
3514 printk_once(KERN_WARNING
3515 "SMB3.11 POSIX Extensions are experimental\n");
3516 } else {
3517 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3518 rc = -EOPNOTSUPP;
3519 goto out_fail;
3520 }
3521 }
3522
3523 /*
3524 * BB Do we need to wrap session_mutex around this TCon call and Unix
3525 * SetFS as we do on SessSetup and reconnect?
3526 */
3527 xid = get_xid();
3528 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3529 volume_info->local_nls);
3530 free_xid(xid);
3531 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
3532 if (rc)
3533 goto out_fail;
3534
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003535 tcon->use_persistent = false;
3536 /* check if SMB2 or later, CIFS does not support persistent handles */
3537 if (volume_info->persistent) {
3538 if (ses->server->vals->protocol_id == 0) {
3539 cifs_dbg(VFS,
3540 "SMB3 or later required for persistent handles\n");
3541 rc = -EOPNOTSUPP;
3542 goto out_fail;
3543 } else if (ses->server->capabilities &
3544 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3545 tcon->use_persistent = true;
3546 else /* persistent handles requested but not supported */ {
3547 cifs_dbg(VFS,
3548 "Persistent handles not supported on share\n");
3549 rc = -EOPNOTSUPP;
3550 goto out_fail;
3551 }
3552 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3553 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3554 && (volume_info->nopersistent == false)) {
3555 cifs_dbg(FYI, "enabling persistent handles\n");
3556 tcon->use_persistent = true;
3557 } else if (volume_info->resilient) {
3558 if (ses->server->vals->protocol_id == 0) {
3559 cifs_dbg(VFS,
3560 "SMB2.1 or later required for resilient handles\n");
3561 rc = -EOPNOTSUPP;
3562 goto out_fail;
3563 }
3564 tcon->use_resilient = true;
3565 }
3566
David Brazdil0f672f62019-12-10 10:32:29 +00003567 /* If the user really knows what they are doing they can override */
3568 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3569 if (volume_info->cache_ro)
3570 cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3571 else if (volume_info->cache_rw)
3572 cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3573 }
3574
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003575 /*
3576 * We can have only one retry value for a connection to a share so for
3577 * resources mounted more than once to the same server share the last
3578 * value passed in for the retry flag is used.
3579 */
3580 tcon->retry = volume_info->retry;
3581 tcon->nocase = volume_info->nocase;
3582 tcon->nohandlecache = volume_info->nohandlecache;
3583 tcon->local_lease = volume_info->local_lease;
David Brazdil0f672f62019-12-10 10:32:29 +00003584 tcon->no_lease = volume_info->no_lease;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003585 INIT_LIST_HEAD(&tcon->pending_opens);
3586
3587 spin_lock(&cifs_tcp_ses_lock);
3588 list_add(&tcon->tcon_list, &ses->tcon_list);
3589 spin_unlock(&cifs_tcp_ses_lock);
3590
3591 cifs_fscache_get_super_cookie(tcon);
3592
3593 return tcon;
3594
3595out_fail:
3596 tconInfoFree(tcon);
3597 return ERR_PTR(rc);
3598}
3599
3600void
3601cifs_put_tlink(struct tcon_link *tlink)
3602{
3603 if (!tlink || IS_ERR(tlink))
3604 return;
3605
3606 if (!atomic_dec_and_test(&tlink->tl_count) ||
3607 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3608 tlink->tl_time = jiffies;
3609 return;
3610 }
3611
3612 if (!IS_ERR(tlink_tcon(tlink)))
3613 cifs_put_tcon(tlink_tcon(tlink));
3614 kfree(tlink);
3615 return;
3616}
3617
3618static int
3619compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3620{
3621 struct cifs_sb_info *old = CIFS_SB(sb);
3622 struct cifs_sb_info *new = mnt_data->cifs_sb;
David Brazdil0f672f62019-12-10 10:32:29 +00003623 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3624 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003625
3626 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3627 return 0;
3628
David Brazdil0f672f62019-12-10 10:32:29 +00003629 if (old->mnt_cifs_serverino_autodisabled)
3630 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3631
3632 if (oldflags != newflags)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003633 return 0;
3634
3635 /*
3636 * We want to share sb only if we don't specify an r/wsize or
3637 * specified r/wsize is greater than or equal to existing one.
3638 */
3639 if (new->wsize && new->wsize < old->wsize)
3640 return 0;
3641
3642 if (new->rsize && new->rsize < old->rsize)
3643 return 0;
3644
3645 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
3646 return 0;
3647
3648 if (old->mnt_file_mode != new->mnt_file_mode ||
3649 old->mnt_dir_mode != new->mnt_dir_mode)
3650 return 0;
3651
3652 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3653 return 0;
3654
3655 if (old->actimeo != new->actimeo)
3656 return 0;
3657
3658 return 1;
3659}
3660
3661static int
3662match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3663{
3664 struct cifs_sb_info *old = CIFS_SB(sb);
3665 struct cifs_sb_info *new = mnt_data->cifs_sb;
Olivier Deprez0e641232021-09-23 10:07:05 +02003666 bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3667 old->prepath;
3668 bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3669 new->prepath;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003670
3671 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
3672 return 1;
3673 else if (!old_set && !new_set)
3674 return 1;
3675
3676 return 0;
3677}
3678
3679int
3680cifs_match_super(struct super_block *sb, void *data)
3681{
3682 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3683 struct smb_vol *volume_info;
3684 struct cifs_sb_info *cifs_sb;
3685 struct TCP_Server_Info *tcp_srv;
3686 struct cifs_ses *ses;
3687 struct cifs_tcon *tcon;
3688 struct tcon_link *tlink;
3689 int rc = 0;
3690
3691 spin_lock(&cifs_tcp_ses_lock);
3692 cifs_sb = CIFS_SB(sb);
3693 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3694 if (IS_ERR(tlink)) {
3695 spin_unlock(&cifs_tcp_ses_lock);
3696 return rc;
3697 }
3698 tcon = tlink_tcon(tlink);
3699 ses = tcon->ses;
3700 tcp_srv = ses->server;
3701
3702 volume_info = mnt_data->vol;
3703
3704 if (!match_server(tcp_srv, volume_info) ||
3705 !match_session(ses, volume_info) ||
3706 !match_tcon(tcon, volume_info) ||
3707 !match_prepath(sb, mnt_data)) {
3708 rc = 0;
3709 goto out;
3710 }
3711
3712 rc = compare_mount_options(sb, mnt_data);
3713out:
3714 spin_unlock(&cifs_tcp_ses_lock);
3715 cifs_put_tlink(tlink);
3716 return rc;
3717}
3718
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003719#ifdef CONFIG_DEBUG_LOCK_ALLOC
3720static struct lock_class_key cifs_key[2];
3721static struct lock_class_key cifs_slock_key[2];
3722
3723static inline void
3724cifs_reclassify_socket4(struct socket *sock)
3725{
3726 struct sock *sk = sock->sk;
3727 BUG_ON(!sock_allow_reclassification(sk));
3728 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3729 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3730}
3731
3732static inline void
3733cifs_reclassify_socket6(struct socket *sock)
3734{
3735 struct sock *sk = sock->sk;
3736 BUG_ON(!sock_allow_reclassification(sk));
3737 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3738 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3739}
3740#else
3741static inline void
3742cifs_reclassify_socket4(struct socket *sock)
3743{
3744}
3745
3746static inline void
3747cifs_reclassify_socket6(struct socket *sock)
3748{
3749}
3750#endif
3751
3752/* See RFC1001 section 14 on representation of Netbios names */
3753static void rfc1002mangle(char *target, char *source, unsigned int length)
3754{
3755 unsigned int i, j;
3756
3757 for (i = 0, j = 0; i < (length); i++) {
3758 /* mask a nibble at a time and encode */
3759 target[j] = 'A' + (0x0F & (source[i] >> 4));
3760 target[j+1] = 'A' + (0x0F & source[i]);
3761 j += 2;
3762 }
3763
3764}
3765
3766static int
3767bind_socket(struct TCP_Server_Info *server)
3768{
3769 int rc = 0;
3770 if (server->srcaddr.ss_family != AF_UNSPEC) {
3771 /* Bind to the specified local IP address */
3772 struct socket *socket = server->ssocket;
3773 rc = socket->ops->bind(socket,
3774 (struct sockaddr *) &server->srcaddr,
3775 sizeof(server->srcaddr));
3776 if (rc < 0) {
3777 struct sockaddr_in *saddr4;
3778 struct sockaddr_in6 *saddr6;
3779 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3780 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3781 if (saddr6->sin6_family == AF_INET6)
David Brazdil0f672f62019-12-10 10:32:29 +00003782 cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003783 &saddr6->sin6_addr, rc);
3784 else
David Brazdil0f672f62019-12-10 10:32:29 +00003785 cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003786 &saddr4->sin_addr.s_addr, rc);
3787 }
3788 }
3789 return rc;
3790}
3791
3792static int
3793ip_rfc1001_connect(struct TCP_Server_Info *server)
3794{
3795 int rc = 0;
3796 /*
3797 * some servers require RFC1001 sessinit before sending
3798 * negprot - BB check reconnection in case where second
3799 * sessinit is sent but no second negprot
3800 */
3801 struct rfc1002_session_packet *ses_init_buf;
3802 struct smb_hdr *smb_buf;
3803 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3804 GFP_KERNEL);
3805 if (ses_init_buf) {
3806 ses_init_buf->trailer.session_req.called_len = 32;
3807
3808 if (server->server_RFC1001_name[0] != 0)
3809 rfc1002mangle(ses_init_buf->trailer.
3810 session_req.called_name,
3811 server->server_RFC1001_name,
3812 RFC1001_NAME_LEN_WITH_NULL);
3813 else
3814 rfc1002mangle(ses_init_buf->trailer.
3815 session_req.called_name,
3816 DEFAULT_CIFS_CALLED_NAME,
3817 RFC1001_NAME_LEN_WITH_NULL);
3818
3819 ses_init_buf->trailer.session_req.calling_len = 32;
3820
3821 /*
3822 * calling name ends in null (byte 16) from old smb
3823 * convention.
3824 */
3825 if (server->workstation_RFC1001_name[0] != 0)
3826 rfc1002mangle(ses_init_buf->trailer.
3827 session_req.calling_name,
3828 server->workstation_RFC1001_name,
3829 RFC1001_NAME_LEN_WITH_NULL);
3830 else
3831 rfc1002mangle(ses_init_buf->trailer.
3832 session_req.calling_name,
3833 "LINUX_CIFS_CLNT",
3834 RFC1001_NAME_LEN_WITH_NULL);
3835
3836 ses_init_buf->trailer.session_req.scope1 = 0;
3837 ses_init_buf->trailer.session_req.scope2 = 0;
3838 smb_buf = (struct smb_hdr *)ses_init_buf;
3839
3840 /* sizeof RFC1002_SESSION_REQUEST with no scope */
3841 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
3842 rc = smb_send(server, smb_buf, 0x44);
3843 kfree(ses_init_buf);
3844 /*
3845 * RFC1001 layer in at least one server
3846 * requires very short break before negprot
3847 * presumably because not expecting negprot
3848 * to follow so fast. This is a simple
3849 * solution that works without
3850 * complicating the code and causes no
3851 * significant slowing down on mount
3852 * for everyone else
3853 */
3854 usleep_range(1000, 2000);
3855 }
3856 /*
3857 * else the negprot may still work without this
3858 * even though malloc failed
3859 */
3860
3861 return rc;
3862}
3863
3864static int
3865generic_ip_connect(struct TCP_Server_Info *server)
3866{
3867 int rc = 0;
3868 __be16 sport;
3869 int slen, sfamily;
3870 struct socket *socket = server->ssocket;
3871 struct sockaddr *saddr;
3872
3873 saddr = (struct sockaddr *) &server->dstaddr;
3874
3875 if (server->dstaddr.ss_family == AF_INET6) {
3876 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3877 slen = sizeof(struct sockaddr_in6);
3878 sfamily = AF_INET6;
3879 } else {
3880 sport = ((struct sockaddr_in *) saddr)->sin_port;
3881 slen = sizeof(struct sockaddr_in);
3882 sfamily = AF_INET;
3883 }
3884
3885 if (socket == NULL) {
3886 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3887 IPPROTO_TCP, &socket, 1);
3888 if (rc < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00003889 cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003890 server->ssocket = NULL;
3891 return rc;
3892 }
3893
3894 /* BB other socket options to set KEEPALIVE, NODELAY? */
3895 cifs_dbg(FYI, "Socket created\n");
3896 server->ssocket = socket;
3897 socket->sk->sk_allocation = GFP_NOFS;
3898 if (sfamily == AF_INET6)
3899 cifs_reclassify_socket6(socket);
3900 else
3901 cifs_reclassify_socket4(socket);
3902 }
3903
3904 rc = bind_socket(server);
3905 if (rc < 0)
3906 return rc;
3907
3908 /*
3909 * Eventually check for other socket options to change from
3910 * the default. sock_setsockopt not used because it expects
3911 * user space buffer
3912 */
3913 socket->sk->sk_rcvtimeo = 7 * HZ;
3914 socket->sk->sk_sndtimeo = 5 * HZ;
3915
3916 /* make the bufsizes depend on wsize/rsize and max requests */
3917 if (server->noautotune) {
3918 if (socket->sk->sk_sndbuf < (200 * 1024))
3919 socket->sk->sk_sndbuf = 200 * 1024;
3920 if (socket->sk->sk_rcvbuf < (140 * 1024))
3921 socket->sk->sk_rcvbuf = 140 * 1024;
3922 }
3923
3924 if (server->tcp_nodelay) {
3925 int val = 1;
3926 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3927 (char *)&val, sizeof(val));
3928 if (rc)
3929 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3930 rc);
3931 }
3932
3933 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
3934 socket->sk->sk_sndbuf,
3935 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3936
David Brazdil0f672f62019-12-10 10:32:29 +00003937 rc = socket->ops->connect(socket, saddr, slen,
3938 server->noblockcnt ? O_NONBLOCK : 0);
3939 /*
3940 * When mounting SMB root file systems, we do not want to block in
3941 * connect. Otherwise bail out and then let cifs_reconnect() perform
3942 * reconnect failover - if possible.
3943 */
3944 if (server->noblockcnt && rc == -EINPROGRESS)
3945 rc = 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003946 if (rc < 0) {
3947 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
3948 sock_release(socket);
3949 server->ssocket = NULL;
3950 return rc;
3951 }
3952
3953 if (sport == htons(RFC1001_PORT))
3954 rc = ip_rfc1001_connect(server);
3955
3956 return rc;
3957}
3958
3959static int
3960ip_connect(struct TCP_Server_Info *server)
3961{
3962 __be16 *sport;
3963 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3964 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3965
3966 if (server->dstaddr.ss_family == AF_INET6)
3967 sport = &addr6->sin6_port;
3968 else
3969 sport = &addr->sin_port;
3970
3971 if (*sport == 0) {
3972 int rc;
3973
3974 /* try with 445 port at first */
3975 *sport = htons(CIFS_PORT);
3976
3977 rc = generic_ip_connect(server);
3978 if (rc >= 0)
3979 return rc;
3980
3981 /* if it failed, try with 139 port */
3982 *sport = htons(RFC1001_PORT);
3983 }
3984
3985 return generic_ip_connect(server);
3986}
3987
3988void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
3989 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
3990{
3991 /* if we are reconnecting then should we check to see if
3992 * any requested capabilities changed locally e.g. via
3993 * remount but we can not do much about it here
3994 * if they have (even if we could detect it by the following)
3995 * Perhaps we could add a backpointer to array of sb from tcon
3996 * or if we change to make all sb to same share the same
3997 * sb as NFS - then we only have one backpointer to sb.
3998 * What if we wanted to mount the server share twice once with
3999 * and once without posixacls or posix paths? */
4000 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
4001
4002 if (vol_info && vol_info->no_linux_ext) {
4003 tcon->fsUnixInfo.Capability = 0;
4004 tcon->unix_ext = 0; /* Unix Extensions disabled */
4005 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
4006 return;
4007 } else if (vol_info)
4008 tcon->unix_ext = 1; /* Unix Extensions supported */
4009
4010 if (tcon->unix_ext == 0) {
4011 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
4012 return;
4013 }
4014
4015 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
4016 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
4017 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
4018 /* check for reconnect case in which we do not
4019 want to change the mount behavior if we can avoid it */
4020 if (vol_info == NULL) {
4021 /* turn off POSIX ACL and PATHNAMES if not set
4022 originally at mount time */
4023 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
4024 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
4025 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
4026 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
4027 cifs_dbg(VFS, "POSIXPATH support change\n");
4028 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
4029 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
4030 cifs_dbg(VFS, "possible reconnect error\n");
4031 cifs_dbg(VFS, "server disabled POSIX path support\n");
4032 }
4033 }
4034
4035 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
4036 cifs_dbg(VFS, "per-share encryption not supported yet\n");
4037
4038 cap &= CIFS_UNIX_CAP_MASK;
4039 if (vol_info && vol_info->no_psx_acl)
4040 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
4041 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
4042 cifs_dbg(FYI, "negotiated posix acl support\n");
4043 if (cifs_sb)
4044 cifs_sb->mnt_cifs_flags |=
4045 CIFS_MOUNT_POSIXACL;
4046 }
4047
4048 if (vol_info && vol_info->posix_paths == 0)
4049 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
4050 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4051 cifs_dbg(FYI, "negotiate posix pathnames\n");
4052 if (cifs_sb)
4053 cifs_sb->mnt_cifs_flags |=
4054 CIFS_MOUNT_POSIX_PATHS;
4055 }
4056
4057 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
4058#ifdef CONFIG_CIFS_DEBUG2
4059 if (cap & CIFS_UNIX_FCNTL_CAP)
4060 cifs_dbg(FYI, "FCNTL cap\n");
4061 if (cap & CIFS_UNIX_EXTATTR_CAP)
4062 cifs_dbg(FYI, "EXTATTR cap\n");
4063 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
4064 cifs_dbg(FYI, "POSIX path cap\n");
4065 if (cap & CIFS_UNIX_XATTR_CAP)
4066 cifs_dbg(FYI, "XATTR cap\n");
4067 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
4068 cifs_dbg(FYI, "POSIX ACL cap\n");
4069 if (cap & CIFS_UNIX_LARGE_READ_CAP)
4070 cifs_dbg(FYI, "very large read cap\n");
4071 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
4072 cifs_dbg(FYI, "very large write cap\n");
4073 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
4074 cifs_dbg(FYI, "transport encryption cap\n");
4075 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
4076 cifs_dbg(FYI, "mandatory transport encryption cap\n");
4077#endif /* CIFS_DEBUG2 */
4078 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
4079 if (vol_info == NULL) {
4080 cifs_dbg(FYI, "resetting capabilities failed\n");
4081 } else
4082 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");
4083
4084 }
4085 }
4086}
4087
4088int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
4089 struct cifs_sb_info *cifs_sb)
4090{
4091 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
4092
4093 spin_lock_init(&cifs_sb->tlink_tree_lock);
4094 cifs_sb->tlink_tree = RB_ROOT;
4095
David Brazdil0f672f62019-12-10 10:32:29 +00004096 cifs_sb->bsize = pvolume_info->bsize;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004097 /*
4098 * Temporarily set r/wsize for matching superblock. If we end up using
4099 * new sb then client will later negotiate it downward if needed.
4100 */
4101 cifs_sb->rsize = pvolume_info->rsize;
4102 cifs_sb->wsize = pvolume_info->wsize;
4103
4104 cifs_sb->mnt_uid = pvolume_info->linux_uid;
4105 cifs_sb->mnt_gid = pvolume_info->linux_gid;
4106 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
4107 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Olivier Deprez0e641232021-09-23 10:07:05 +02004108 cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004109 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
4110
4111 cifs_sb->actimeo = pvolume_info->actimeo;
4112 cifs_sb->local_nls = pvolume_info->local_nls;
4113
David Brazdil0f672f62019-12-10 10:32:29 +00004114 if (pvolume_info->nodfs)
4115 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004116 if (pvolume_info->noperm)
4117 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4118 if (pvolume_info->setuids)
4119 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
4120 if (pvolume_info->setuidfromacl)
4121 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
4122 if (pvolume_info->server_ino)
4123 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4124 if (pvolume_info->remap)
4125 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
4126 if (pvolume_info->sfu_remap)
4127 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4128 if (pvolume_info->no_xattr)
4129 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4130 if (pvolume_info->sfu_emul)
4131 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4132 if (pvolume_info->nobrl)
4133 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
4134 if (pvolume_info->nohandlecache)
4135 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
4136 if (pvolume_info->nostrictsync)
4137 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
4138 if (pvolume_info->mand_lock)
4139 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
4140 if (pvolume_info->rwpidforward)
4141 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
David Brazdil0f672f62019-12-10 10:32:29 +00004142 if (pvolume_info->mode_ace)
4143 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004144 if (pvolume_info->cifs_acl)
4145 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
4146 if (pvolume_info->backupuid_specified) {
4147 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
4148 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
4149 }
4150 if (pvolume_info->backupgid_specified) {
4151 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
4152 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
4153 }
4154 if (pvolume_info->override_uid)
4155 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
4156 if (pvolume_info->override_gid)
4157 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
4158 if (pvolume_info->dynperm)
4159 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
4160 if (pvolume_info->fsc)
4161 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
4162 if (pvolume_info->multiuser)
4163 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
4164 CIFS_MOUNT_NO_PERM);
4165 if (pvolume_info->strict_io)
4166 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
4167 if (pvolume_info->direct_io) {
4168 cifs_dbg(FYI, "mounting share using direct i/o\n");
4169 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
4170 }
David Brazdil0f672f62019-12-10 10:32:29 +00004171 if (pvolume_info->cache_ro) {
4172 cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4173 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
4174 } else if (pvolume_info->cache_rw) {
4175 cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4176 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4177 CIFS_MOUNT_RW_CACHE);
4178 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004179 if (pvolume_info->mfsymlinks) {
4180 if (pvolume_info->sfu_emul) {
4181 /*
4182 * Our SFU ("Services for Unix" emulation does not allow
4183 * creating symlinks but does allow reading existing SFU
4184 * symlinks (it does allow both creating and reading SFU
4185 * style mknod and FIFOs though). When "mfsymlinks" and
4186 * "sfu" are both enabled at the same time, it allows
4187 * reading both types of symlinks, but will only create
4188 * them with mfsymlinks format. This allows better
4189 * Apple compatibility (probably better for Samba too)
4190 * while still recognizing old Windows style symlinks.
4191 */
4192 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
4193 }
4194 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
4195 }
4196
4197 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
4198 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
4199
4200 if (pvolume_info->prepath) {
4201 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
4202 if (cifs_sb->prepath == NULL)
4203 return -ENOMEM;
4204 }
4205
4206 return 0;
4207}
4208
David Brazdil0f672f62019-12-10 10:32:29 +00004209void
4210cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004211{
4212 kfree(volume_info->username);
4213 kzfree(volume_info->password);
4214 kfree(volume_info->UNC);
4215 kfree(volume_info->domainname);
4216 kfree(volume_info->iocharset);
4217 kfree(volume_info->prepath);
4218}
4219
4220void
4221cifs_cleanup_volume_info(struct smb_vol *volume_info)
4222{
4223 if (!volume_info)
4224 return;
David Brazdil0f672f62019-12-10 10:32:29 +00004225 cifs_cleanup_volume_info_contents(volume_info);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004226 kfree(volume_info);
4227}
4228
David Brazdil0f672f62019-12-10 10:32:29 +00004229/* Release all succeed connections */
4230static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4231 unsigned int xid,
4232 struct TCP_Server_Info *server,
4233 struct cifs_ses *ses, struct cifs_tcon *tcon)
4234{
4235 int rc = 0;
4236
4237 if (tcon)
4238 cifs_put_tcon(tcon);
4239 else if (ses)
4240 cifs_put_smb_ses(ses);
4241 else if (server)
4242 cifs_put_tcp_session(server, 0);
4243 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4244 free_xid(xid);
4245}
4246
4247/* Get connections for tcp, ses and tcon */
4248static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4249 unsigned int *xid,
4250 struct TCP_Server_Info **nserver,
4251 struct cifs_ses **nses, struct cifs_tcon **ntcon)
4252{
4253 int rc = 0;
4254 struct TCP_Server_Info *server;
4255 struct cifs_ses *ses;
4256 struct cifs_tcon *tcon;
4257
4258 *nserver = NULL;
4259 *nses = NULL;
4260 *ntcon = NULL;
4261
4262 *xid = get_xid();
4263
4264 /* get a reference to a tcp session */
4265 server = cifs_get_tcp_session(vol);
4266 if (IS_ERR(server)) {
4267 rc = PTR_ERR(server);
4268 return rc;
4269 }
4270
4271 *nserver = server;
4272
4273 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
4274 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4275 else
4276 server->max_credits = vol->max_credits;
4277
4278 /* get a reference to a SMB session */
4279 ses = cifs_get_smb_ses(server, vol);
4280 if (IS_ERR(ses)) {
4281 rc = PTR_ERR(ses);
4282 return rc;
4283 }
4284
4285 *nses = ses;
4286
4287 if ((vol->persistent == true) && (!(ses->server->capabilities &
4288 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
4289 cifs_server_dbg(VFS, "persistent handles not supported by server\n");
4290 return -EOPNOTSUPP;
4291 }
4292
4293 /* search for existing tcon to this server share */
4294 tcon = cifs_get_tcon(ses, vol);
4295 if (IS_ERR(tcon)) {
4296 rc = PTR_ERR(tcon);
4297 return rc;
4298 }
4299
4300 *ntcon = tcon;
4301
4302 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4303 if (tcon->posix_extensions)
4304 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4305
4306 /* tell server which Unix caps we support */
4307 if (cap_unix(tcon->ses)) {
4308 /*
4309 * reset of caps checks mount to see if unix extensions disabled
4310 * for just this mount.
4311 */
4312 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4313 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4314 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4315 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4316 return -EACCES;
4317 } else
4318 tcon->unix_ext = 0; /* server does not support them */
4319
4320 /* do not care if a following call succeed - informational */
4321 if (!tcon->pipe && server->ops->qfs_tcon) {
4322 server->ops->qfs_tcon(*xid, tcon);
4323 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4324 if (tcon->fsDevInfo.DeviceCharacteristics &
4325 cpu_to_le32(FILE_READ_ONLY_DEVICE))
4326 cifs_dbg(VFS, "mounted to read only share\n");
4327 else if ((cifs_sb->mnt_cifs_flags &
4328 CIFS_MOUNT_RW_CACHE) == 0)
4329 cifs_dbg(VFS, "read only mount of RW share\n");
4330 /* no need to log a RW mount of a typical RW share */
4331 }
4332 }
4333
4334 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4335 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4336
4337 return 0;
4338}
4339
4340static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4341 struct cifs_tcon *tcon)
4342{
4343 struct tcon_link *tlink;
4344
4345 /* hang the tcon off of the superblock */
4346 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4347 if (tlink == NULL)
4348 return -ENOMEM;
4349
4350 tlink->tl_uid = ses->linux_uid;
4351 tlink->tl_tcon = tcon;
4352 tlink->tl_time = jiffies;
4353 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4354 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4355
4356 cifs_sb->master_tlink = tlink;
4357 spin_lock(&cifs_sb->tlink_tree_lock);
4358 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4359 spin_unlock(&cifs_sb->tlink_tree_lock);
4360
4361 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4362 TLINK_IDLE_EXPIRE);
4363 return 0;
4364}
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004365
4366#ifdef CONFIG_CIFS_DFS_UPCALL
4367/*
4368 * cifs_build_path_to_root returns full path to root when we do not have an
4369 * exiting connection (tcon)
4370 */
4371static char *
4372build_unc_path_to_root(const struct smb_vol *vol,
David Brazdil0f672f62019-12-10 10:32:29 +00004373 const struct cifs_sb_info *cifs_sb, bool useppath)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004374{
4375 char *full_path, *pos;
David Brazdil0f672f62019-12-10 10:32:29 +00004376 unsigned int pplen = useppath && vol->prepath ?
4377 strlen(vol->prepath) + 1 : 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004378 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
4379
David Brazdil0f672f62019-12-10 10:32:29 +00004380 if (unc_len > MAX_TREE_SIZE)
4381 return ERR_PTR(-EINVAL);
4382
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004383 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
4384 if (full_path == NULL)
4385 return ERR_PTR(-ENOMEM);
4386
David Brazdil0f672f62019-12-10 10:32:29 +00004387 memcpy(full_path, vol->UNC, unc_len);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004388 pos = full_path + unc_len;
4389
4390 if (pplen) {
4391 *pos = CIFS_DIR_SEP(cifs_sb);
David Brazdil0f672f62019-12-10 10:32:29 +00004392 memcpy(pos + 1, vol->prepath, pplen);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004393 pos += pplen;
4394 }
4395
4396 *pos = '\0'; /* add trailing null */
4397 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
4398 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
4399 return full_path;
4400}
4401
David Brazdil0f672f62019-12-10 10:32:29 +00004402/**
4403 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4404 *
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004405 *
4406 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4407 * to a string containing updated options for the submount. Otherwise it
4408 * will be left untouched.
4409 *
4410 * Returns the rc from get_dfs_path to the caller, which can be used to
4411 * determine whether there were referrals.
4412 */
4413static int
4414expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
4415 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
4416 int check_prefix)
4417{
4418 int rc;
David Brazdil0f672f62019-12-10 10:32:29 +00004419 struct dfs_info3_param referral = {0};
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004420 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4421
David Brazdil0f672f62019-12-10 10:32:29 +00004422 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4423 return -EREMOTE;
4424
4425 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004426 if (IS_ERR(full_path))
4427 return PTR_ERR(full_path);
4428
4429 /* For DFS paths, skip the first '\' of the UNC */
4430 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4431
David Brazdil0f672f62019-12-10 10:32:29 +00004432 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4433 ref_path, &referral, NULL);
4434 if (!rc) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004435 char *fake_devname = NULL;
4436
4437 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
David Brazdil0f672f62019-12-10 10:32:29 +00004438 full_path + 1, &referral,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004439 &fake_devname);
David Brazdil0f672f62019-12-10 10:32:29 +00004440 free_dfs_info_param(&referral);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004441
4442 if (IS_ERR(mdata)) {
4443 rc = PTR_ERR(mdata);
4444 mdata = NULL;
4445 } else {
David Brazdil0f672f62019-12-10 10:32:29 +00004446 cifs_cleanup_volume_info_contents(volume_info);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004447 rc = cifs_setup_volume_info(volume_info, mdata,
David Brazdil0f672f62019-12-10 10:32:29 +00004448 fake_devname, false);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004449 }
4450 kfree(fake_devname);
4451 kfree(cifs_sb->mountdata);
4452 cifs_sb->mountdata = mdata;
4453 }
4454 kfree(full_path);
4455 return rc;
4456}
David Brazdil0f672f62019-12-10 10:32:29 +00004457
4458static inline int get_next_dfs_tgt(const char *path,
4459 struct dfs_cache_tgt_list *tgt_list,
4460 struct dfs_cache_tgt_iterator **tgt_it)
4461{
4462 if (!*tgt_it)
4463 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4464 else
4465 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4466 return !*tgt_it ? -EHOSTDOWN : 0;
4467}
4468
4469static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4470 struct smb_vol *fake_vol, struct smb_vol *vol)
4471{
4472 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4473 int len = strlen(tgt) + 2;
4474 char *new_unc;
4475
4476 new_unc = kmalloc(len, GFP_KERNEL);
4477 if (!new_unc)
4478 return -ENOMEM;
4479 scnprintf(new_unc, len, "\\%s", tgt);
4480
4481 kfree(vol->UNC);
4482 vol->UNC = new_unc;
4483
4484 if (fake_vol->prepath) {
4485 kfree(vol->prepath);
4486 vol->prepath = fake_vol->prepath;
4487 fake_vol->prepath = NULL;
4488 }
4489 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4490
4491 return 0;
4492}
4493
4494static int setup_dfs_tgt_conn(const char *path,
4495 const struct dfs_cache_tgt_iterator *tgt_it,
4496 struct cifs_sb_info *cifs_sb,
4497 struct smb_vol *vol,
4498 unsigned int *xid,
4499 struct TCP_Server_Info **server,
4500 struct cifs_ses **ses,
4501 struct cifs_tcon **tcon)
4502{
4503 int rc;
4504 struct dfs_info3_param ref = {0};
4505 char *mdata = NULL, *fake_devname = NULL;
4506 struct smb_vol fake_vol = {NULL};
4507
4508 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4509
4510 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4511 if (rc)
4512 return rc;
4513
4514 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4515 &fake_devname);
4516 free_dfs_info_param(&ref);
4517
4518 if (IS_ERR(mdata)) {
4519 rc = PTR_ERR(mdata);
4520 mdata = NULL;
4521 } else {
4522 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4523 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4524 false);
4525 }
4526 kfree(mdata);
4527 kfree(fake_devname);
4528
4529 if (!rc) {
4530 /*
4531 * We use a 'fake_vol' here because we need pass it down to the
4532 * mount_{get,put} functions to test connection against new DFS
4533 * targets.
4534 */
4535 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4536 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4537 tcon);
4538 if (!rc) {
4539 /*
4540 * We were able to connect to new target server.
4541 * Update current volume info with new target server.
4542 */
4543 rc = update_vol_info(tgt_it, &fake_vol, vol);
4544 }
4545 }
4546 cifs_cleanup_volume_info_contents(&fake_vol);
4547 return rc;
4548}
4549
4550static int mount_do_dfs_failover(const char *path,
4551 struct cifs_sb_info *cifs_sb,
4552 struct smb_vol *vol,
4553 struct cifs_ses *root_ses,
4554 unsigned int *xid,
4555 struct TCP_Server_Info **server,
4556 struct cifs_ses **ses,
4557 struct cifs_tcon **tcon)
4558{
4559 int rc;
4560 struct dfs_cache_tgt_list tgt_list;
4561 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4562
4563 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4564 return -EOPNOTSUPP;
4565
4566 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4567 if (rc)
4568 return rc;
4569
4570 for (;;) {
4571 /* Get next DFS target server - if any */
4572 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4573 if (rc)
4574 break;
4575 /* Connect to next DFS target */
4576 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4577 ses, tcon);
4578 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4579 break;
4580 }
4581 if (!rc) {
4582 /*
4583 * Update DFS target hint in DFS referral cache with the target
4584 * server we successfully reconnected to.
4585 */
4586 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4587 cifs_sb->local_nls,
4588 cifs_remap(cifs_sb), path,
4589 tgt_it);
4590 }
4591 dfs_cache_free_tgts(&tgt_list);
4592 return rc;
4593}
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004594#endif
4595
David Brazdil0f672f62019-12-10 10:32:29 +00004596int
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004597cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
4598 const char *devname, bool is_smb3)
4599{
4600 int rc = 0;
4601
4602 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
4603 return -EINVAL;
4604
4605 if (volume_info->nullauth) {
4606 cifs_dbg(FYI, "Anonymous login\n");
4607 kfree(volume_info->username);
4608 volume_info->username = NULL;
4609 } else if (volume_info->username) {
4610 /* BB fixme parse for domain name here */
4611 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
4612 } else {
4613 cifs_dbg(VFS, "No username specified\n");
4614 /* In userspace mount helper we can get user name from alternate
4615 locations such as env variables and files on disk */
4616 return -EINVAL;
4617 }
4618
4619 /* this is needed for ASCII cp to Unicode converts */
4620 if (volume_info->iocharset == NULL) {
4621 /* load_nls_default cannot return null */
4622 volume_info->local_nls = load_nls_default();
4623 } else {
4624 volume_info->local_nls = load_nls(volume_info->iocharset);
4625 if (volume_info->local_nls == NULL) {
4626 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
4627 volume_info->iocharset);
4628 return -ELIBACC;
4629 }
4630 }
4631
4632 return rc;
4633}
4634
4635struct smb_vol *
4636cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
4637{
4638 int rc;
4639 struct smb_vol *volume_info;
4640
4641 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
4642 if (!volume_info)
4643 return ERR_PTR(-ENOMEM);
4644
4645 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
4646 if (rc) {
4647 cifs_cleanup_volume_info(volume_info);
4648 volume_info = ERR_PTR(rc);
4649 }
4650
4651 return volume_info;
4652}
4653
4654static int
4655cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4656 unsigned int xid,
4657 struct cifs_tcon *tcon,
4658 struct cifs_sb_info *cifs_sb,
David Brazdil0f672f62019-12-10 10:32:29 +00004659 char *full_path,
4660 int added_treename)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004661{
4662 int rc;
4663 char *s;
4664 char sep, tmp;
David Brazdil0f672f62019-12-10 10:32:29 +00004665 int skip = added_treename ? 1 : 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004666
4667 sep = CIFS_DIR_SEP(cifs_sb);
4668 s = full_path;
4669
4670 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4671 while (rc == 0) {
4672 /* skip separators */
4673 while (*s == sep)
4674 s++;
4675 if (!*s)
4676 break;
4677 /* next separator */
4678 while (*s && *s != sep)
4679 s++;
David Brazdil0f672f62019-12-10 10:32:29 +00004680 /*
4681 * if the treename is added, we then have to skip the first
4682 * part within the separators
4683 */
4684 if (skip) {
4685 skip = 0;
4686 continue;
4687 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004688 /*
4689 * temporarily null-terminate the path at the end of
4690 * the current component
4691 */
4692 tmp = *s;
4693 *s = 0;
4694 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4695 full_path);
4696 *s = tmp;
4697 }
4698 return rc;
4699}
4700
David Brazdil0f672f62019-12-10 10:32:29 +00004701/*
4702 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4703 * otherwise 0.
4704 */
4705static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4706 const unsigned int xid,
4707 struct TCP_Server_Info *server,
4708 struct cifs_tcon *tcon)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004709{
4710 int rc;
David Brazdil0f672f62019-12-10 10:32:29 +00004711 char *full_path;
4712
4713 if (!server->ops->is_path_accessible)
4714 return -EOPNOTSUPP;
4715
4716 /*
4717 * cifs_build_path_to_root works only when we have a valid tcon
4718 */
4719 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4720 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4721 if (full_path == NULL)
4722 return -ENOMEM;
4723
4724 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4725
4726 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4727 full_path);
4728 if (rc != 0 && rc != -EREMOTE) {
4729 kfree(full_path);
4730 return rc;
4731 }
4732
4733 if (rc != -EREMOTE) {
4734 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
4735 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
4736 if (rc != 0) {
4737 cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
4738 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4739 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4740 rc = 0;
4741 }
4742 }
4743
4744 kfree(full_path);
4745 return rc;
4746}
4747
4748#ifdef CONFIG_CIFS_DFS_UPCALL
Olivier Deprez0e641232021-09-23 10:07:05 +02004749static inline void set_root_tcon(struct cifs_sb_info *cifs_sb,
4750 struct cifs_tcon *tcon,
4751 struct cifs_tcon **root)
4752{
4753 spin_lock(&cifs_tcp_ses_lock);
4754 tcon->tc_count++;
4755 tcon->remap = cifs_remap(cifs_sb);
4756 spin_unlock(&cifs_tcp_ses_lock);
4757 *root = tcon;
4758}
4759
David Brazdil0f672f62019-12-10 10:32:29 +00004760int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4761{
4762 int rc = 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004763 unsigned int xid;
4764 struct cifs_ses *ses;
David Brazdil0f672f62019-12-10 10:32:29 +00004765 struct cifs_tcon *root_tcon = NULL;
4766 struct cifs_tcon *tcon = NULL;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004767 struct TCP_Server_Info *server;
David Brazdil0f672f62019-12-10 10:32:29 +00004768 char *root_path = NULL, *full_path = NULL;
4769 char *old_mountdata, *origin_mountdata = NULL;
4770 int count;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004771
David Brazdil0f672f62019-12-10 10:32:29 +00004772 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4773 if (!rc && tcon) {
4774 /* If not a standalone DFS root, then check if path is remote */
4775 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4776 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4777 NULL);
4778 if (rc) {
4779 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4780 if (!rc)
4781 goto out;
4782 if (rc != -EREMOTE)
4783 goto error;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004784 }
David Brazdil0f672f62019-12-10 10:32:29 +00004785 }
4786 /*
4787 * If first DFS target server went offline and we failed to connect it,
4788 * server and ses pointers are NULL at this point, though we still have
4789 * chance to get a cached DFS referral in expand_dfs_referral() and
4790 * retry next target available in it.
4791 *
4792 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4793 * performed against DFS path and *no* requests will be sent to server
4794 * for any new DFS referrals. Hence it's safe to skip checking whether
4795 * server or ses ptr is NULL.
4796 */
4797 if (rc == -EACCES || rc == -EOPNOTSUPP)
4798 goto error;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004799
David Brazdil0f672f62019-12-10 10:32:29 +00004800 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4801 if (IS_ERR(root_path)) {
4802 rc = PTR_ERR(root_path);
4803 root_path = NULL;
4804 goto error;
4805 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004806
David Brazdil0f672f62019-12-10 10:32:29 +00004807 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4808 if (IS_ERR(full_path)) {
4809 rc = PTR_ERR(full_path);
4810 full_path = NULL;
4811 goto error;
4812 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004813 /*
4814 * Perform an unconditional check for whether there are DFS
4815 * referrals for this path without prefix, to provide support
4816 * for DFS referrals from w2k8 servers which don't seem to respond
4817 * with PATH_NOT_COVERED to requests that include the prefix.
4818 * Chase the referral if found, otherwise continue normally.
4819 */
David Brazdil0f672f62019-12-10 10:32:29 +00004820 old_mountdata = cifs_sb->mountdata;
4821 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004822
David Brazdil0f672f62019-12-10 10:32:29 +00004823 if (cifs_sb->mountdata == NULL) {
4824 rc = -ENOENT;
4825 goto error;
4826 }
4827
4828 /* Save DFS root volume information for DFS refresh worker */
4829 origin_mountdata = kstrndup(cifs_sb->mountdata,
4830 strlen(cifs_sb->mountdata), GFP_KERNEL);
4831 if (!origin_mountdata) {
4832 rc = -ENOMEM;
4833 goto error;
4834 }
4835
4836 if (cifs_sb->mountdata != old_mountdata) {
4837 /* If we were redirected, reconnect to new target server */
4838 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4839 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4840 }
4841 if (rc) {
4842 if (rc == -EACCES || rc == -EOPNOTSUPP)
4843 goto error;
4844 /* Perform DFS failover to any other DFS targets */
4845 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4846 &xid, &server, &ses, &tcon);
4847 if (rc)
4848 goto error;
4849 }
4850
4851 kfree(root_path);
4852 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4853 if (IS_ERR(root_path)) {
4854 rc = PTR_ERR(root_path);
4855 root_path = NULL;
4856 goto error;
4857 }
4858 /* Cache out resolved root server */
4859 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4860 root_path + 1, NULL, NULL);
Olivier Deprez0e641232021-09-23 10:07:05 +02004861 kfree(root_path);
David Brazdil0f672f62019-12-10 10:32:29 +00004862 root_path = NULL;
David Brazdil0f672f62019-12-10 10:32:29 +00004863
Olivier Deprez0e641232021-09-23 10:07:05 +02004864 set_root_tcon(cifs_sb, tcon, &root_tcon);
David Brazdil0f672f62019-12-10 10:32:29 +00004865
4866 for (count = 1; ;) {
4867 if (!rc && tcon) {
4868 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4869 if (!rc || rc != -EREMOTE)
4870 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004871 }
4872 /*
David Brazdil0f672f62019-12-10 10:32:29 +00004873 * BB: when we implement proper loop detection,
4874 * we will remove this check. But now we need it
4875 * to prevent an indefinite loop if 'DFS tree' is
4876 * misconfigured (i.e. has loops).
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004877 */
David Brazdil0f672f62019-12-10 10:32:29 +00004878 if (count++ > MAX_NESTED_LINKS) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004879 rc = -ELOOP;
David Brazdil0f672f62019-12-10 10:32:29 +00004880 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004881 }
4882
David Brazdil0f672f62019-12-10 10:32:29 +00004883 kfree(full_path);
4884 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4885 if (IS_ERR(full_path)) {
4886 rc = PTR_ERR(full_path);
4887 full_path = NULL;
4888 break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004889 }
David Brazdil0f672f62019-12-10 10:32:29 +00004890
4891 old_mountdata = cifs_sb->mountdata;
4892 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
4893 true);
4894 if (rc)
4895 break;
4896
4897 if (cifs_sb->mountdata != old_mountdata) {
4898 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4899 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4900 &tcon);
Olivier Deprez0e641232021-09-23 10:07:05 +02004901 /*
4902 * Ensure that DFS referrals go through new root server.
4903 */
4904 if (!rc && tcon &&
4905 (tcon->share_flags & (SHI1005_FLAGS_DFS |
4906 SHI1005_FLAGS_DFS_ROOT))) {
4907 cifs_put_tcon(root_tcon);
4908 set_root_tcon(cifs_sb, tcon, &root_tcon);
4909 }
David Brazdil0f672f62019-12-10 10:32:29 +00004910 }
4911 if (rc) {
4912 if (rc == -EACCES || rc == -EOPNOTSUPP)
4913 break;
4914 /* Perform DFS failover to any other DFS targets */
4915 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4916 root_tcon->ses, &xid,
4917 &server, &ses, &tcon);
4918 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4919 !ses)
4920 goto error;
4921 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004922 }
David Brazdil0f672f62019-12-10 10:32:29 +00004923 cifs_put_tcon(root_tcon);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004924
4925 if (rc)
David Brazdil0f672f62019-12-10 10:32:29 +00004926 goto error;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004927
David Brazdil0f672f62019-12-10 10:32:29 +00004928 spin_lock(&cifs_tcp_ses_lock);
4929 if (!tcon->dfs_path) {
4930 /* Save full path in new tcon to do failover when reconnecting tcons */
4931 tcon->dfs_path = full_path;
4932 full_path = NULL;
4933 tcon->remap = cifs_remap(cifs_sb);
4934 }
4935 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
4936 strlen(tcon->dfs_path),
4937 GFP_ATOMIC);
4938 if (!cifs_sb->origin_fullpath) {
4939 spin_unlock(&cifs_tcp_ses_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004940 rc = -ENOMEM;
David Brazdil0f672f62019-12-10 10:32:29 +00004941 goto error;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004942 }
David Brazdil0f672f62019-12-10 10:32:29 +00004943 spin_unlock(&cifs_tcp_ses_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004944
David Brazdil0f672f62019-12-10 10:32:29 +00004945 rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004946 if (rc) {
David Brazdil0f672f62019-12-10 10:32:29 +00004947 kfree(cifs_sb->origin_fullpath);
4948 goto error;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004949 }
David Brazdil0f672f62019-12-10 10:32:29 +00004950 /*
4951 * After reconnecting to a different server, unique ids won't
4952 * match anymore, so we disable serverino. This prevents
4953 * dentry revalidation to think the dentry are stale (ESTALE).
4954 */
4955 cifs_autodisable_serverino(cifs_sb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004956out:
4957 free_xid(xid);
David Brazdil0f672f62019-12-10 10:32:29 +00004958 return mount_setup_tlink(cifs_sb, ses, tcon);
4959
4960error:
4961 kfree(full_path);
4962 kfree(root_path);
4963 kfree(origin_mountdata);
4964 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004965 return rc;
4966}
David Brazdil0f672f62019-12-10 10:32:29 +00004967#else
4968int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4969{
4970 int rc = 0;
4971 unsigned int xid;
4972 struct cifs_ses *ses;
4973 struct cifs_tcon *tcon;
4974 struct TCP_Server_Info *server;
4975
4976 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4977 if (rc)
4978 goto error;
4979
4980 if (tcon) {
4981 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4982 if (rc == -EREMOTE)
4983 rc = -EOPNOTSUPP;
4984 if (rc)
4985 goto error;
4986 }
4987
4988 free_xid(xid);
4989
4990 return mount_setup_tlink(cifs_sb, ses, tcon);
4991
4992error:
4993 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4994 return rc;
4995}
4996#endif
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00004997
4998/*
4999 * Issue a TREE_CONNECT request.
5000 */
5001int
5002CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
5003 const char *tree, struct cifs_tcon *tcon,
5004 const struct nls_table *nls_codepage)
5005{
5006 struct smb_hdr *smb_buffer;
5007 struct smb_hdr *smb_buffer_response;
5008 TCONX_REQ *pSMB;
5009 TCONX_RSP *pSMBr;
5010 unsigned char *bcc_ptr;
5011 int rc = 0;
5012 int length;
5013 __u16 bytes_left, count;
5014
5015 if (ses == NULL)
5016 return -EIO;
5017
5018 smb_buffer = cifs_buf_get();
5019 if (smb_buffer == NULL)
5020 return -ENOMEM;
5021
5022 smb_buffer_response = smb_buffer;
5023
5024 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
5025 NULL /*no tid */ , 4 /*wct */ );
5026
5027 smb_buffer->Mid = get_next_mid(ses->server);
5028 smb_buffer->Uid = ses->Suid;
5029 pSMB = (TCONX_REQ *) smb_buffer;
5030 pSMBr = (TCONX_RSP *) smb_buffer_response;
5031
5032 pSMB->AndXCommand = 0xFF;
5033 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
5034 bcc_ptr = &pSMB->Password[0];
5035 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
5036 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
5037 *bcc_ptr = 0; /* password is null byte */
5038 bcc_ptr++; /* skip password */
5039 /* already aligned so no need to do it below */
5040 } else {
5041 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
5042 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
5043 specified as required (when that support is added to
5044 the vfs in the future) as only NTLM or the much
5045 weaker LANMAN (which we do not send by default) is accepted
5046 by Samba (not sure whether other servers allow
5047 NTLMv2 password here) */
5048#ifdef CONFIG_CIFS_WEAK_PW_HASH
5049 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
5050 (ses->sectype == LANMAN))
5051 calc_lanman_hash(tcon->password, ses->server->cryptkey,
5052 ses->server->sec_mode &
5053 SECMODE_PW_ENCRYPT ? true : false,
5054 bcc_ptr);
5055 else
5056#endif /* CIFS_WEAK_PW_HASH */
5057 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
5058 bcc_ptr, nls_codepage);
5059 if (rc) {
5060 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
5061 __func__, rc);
5062 cifs_buf_release(smb_buffer);
5063 return rc;
5064 }
5065
5066 bcc_ptr += CIFS_AUTH_RESP_SIZE;
5067 if (ses->capabilities & CAP_UNICODE) {
5068 /* must align unicode strings */
5069 *bcc_ptr = 0; /* null byte password */
5070 bcc_ptr++;
5071 }
5072 }
5073
5074 if (ses->server->sign)
5075 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
5076
5077 if (ses->capabilities & CAP_STATUS32) {
5078 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
5079 }
5080 if (ses->capabilities & CAP_DFS) {
5081 smb_buffer->Flags2 |= SMBFLG2_DFS;
5082 }
5083 if (ses->capabilities & CAP_UNICODE) {
5084 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
5085 length =
5086 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
5087 6 /* max utf8 char length in bytes */ *
5088 (/* server len*/ + 256 /* share len */), nls_codepage);
5089 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
5090 bcc_ptr += 2; /* skip trailing null */
5091 } else { /* ASCII */
5092 strcpy(bcc_ptr, tree);
5093 bcc_ptr += strlen(tree) + 1;
5094 }
5095 strcpy(bcc_ptr, "?????");
5096 bcc_ptr += strlen("?????");
5097 bcc_ptr += 1;
5098 count = bcc_ptr - &pSMB->Password[0];
5099 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
5100 pSMB->hdr.smb_buf_length) + count);
5101 pSMB->ByteCount = cpu_to_le16(count);
5102
5103 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
5104 0);
5105
5106 /* above now done in SendReceive */
5107 if (rc == 0) {
5108 bool is_unicode;
5109
5110 tcon->tidStatus = CifsGood;
5111 tcon->need_reconnect = false;
5112 tcon->tid = smb_buffer_response->Tid;
5113 bcc_ptr = pByteArea(smb_buffer_response);
5114 bytes_left = get_bcc(smb_buffer_response);
5115 length = strnlen(bcc_ptr, bytes_left - 2);
5116 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
5117 is_unicode = true;
5118 else
5119 is_unicode = false;
5120
5121
5122 /* skip service field (NB: this field is always ASCII) */
5123 if (length == 3) {
5124 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
5125 (bcc_ptr[2] == 'C')) {
5126 cifs_dbg(FYI, "IPC connection\n");
5127 tcon->ipc = true;
5128 tcon->pipe = true;
5129 }
5130 } else if (length == 2) {
5131 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
5132 /* the most common case */
5133 cifs_dbg(FYI, "disk share connection\n");
5134 }
5135 }
5136 bcc_ptr += length + 1;
5137 bytes_left -= (length + 1);
5138 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
5139
5140 /* mostly informational -- no need to fail on error here */
5141 kfree(tcon->nativeFileSystem);
5142 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
5143 bytes_left, is_unicode,
5144 nls_codepage);
5145
5146 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
5147
5148 if ((smb_buffer_response->WordCount == 3) ||
5149 (smb_buffer_response->WordCount == 7))
5150 /* field is in same location */
5151 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
5152 else
5153 tcon->Flags = 0;
5154 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
5155 }
5156
5157 cifs_buf_release(smb_buffer);
5158 return rc;
5159}
5160
5161static void delayed_free(struct rcu_head *p)
5162{
5163 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
5164 unload_nls(sbi->local_nls);
5165 kfree(sbi);
5166}
5167
5168void
5169cifs_umount(struct cifs_sb_info *cifs_sb)
5170{
5171 struct rb_root *root = &cifs_sb->tlink_tree;
5172 struct rb_node *node;
5173 struct tcon_link *tlink;
5174
5175 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
5176
5177 spin_lock(&cifs_sb->tlink_tree_lock);
5178 while ((node = rb_first(root))) {
5179 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5180 cifs_get_tlink(tlink);
5181 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5182 rb_erase(node, root);
5183
5184 spin_unlock(&cifs_sb->tlink_tree_lock);
5185 cifs_put_tlink(tlink);
5186 spin_lock(&cifs_sb->tlink_tree_lock);
5187 }
5188 spin_unlock(&cifs_sb->tlink_tree_lock);
5189
5190 kfree(cifs_sb->mountdata);
5191 kfree(cifs_sb->prepath);
David Brazdil0f672f62019-12-10 10:32:29 +00005192#ifdef CONFIG_CIFS_DFS_UPCALL
5193 dfs_cache_del_vol(cifs_sb->origin_fullpath);
5194 kfree(cifs_sb->origin_fullpath);
5195#endif
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00005196 call_rcu(&cifs_sb->rcu, delayed_free);
5197}
5198
5199int
5200cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
5201{
5202 int rc = 0;
5203 struct TCP_Server_Info *server = ses->server;
5204
5205 if (!server->ops->need_neg || !server->ops->negotiate)
5206 return -ENOSYS;
5207
5208 /* only send once per connect */
5209 if (!server->ops->need_neg(server))
5210 return 0;
5211
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00005212 rc = server->ops->negotiate(xid, ses);
5213 if (rc == 0) {
5214 spin_lock(&GlobalMid_Lock);
5215 if (server->tcpStatus == CifsNeedNegotiate)
5216 server->tcpStatus = CifsGood;
5217 else
5218 rc = -EHOSTDOWN;
5219 spin_unlock(&GlobalMid_Lock);
5220 }
5221
5222 return rc;
5223}
5224
5225int
5226cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
5227 struct nls_table *nls_info)
5228{
5229 int rc = -ENOSYS;
5230 struct TCP_Server_Info *server = ses->server;
5231
5232 ses->capabilities = server->capabilities;
5233 if (linuxExtEnabled == 0)
5234 ses->capabilities &= (~server->vals->cap_unix);
5235
5236 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
5237 server->sec_mode, server->capabilities, server->timeAdj);
5238
5239 if (ses->auth_key.response) {
5240 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
5241 ses->auth_key.response);
5242 kfree(ses->auth_key.response);
5243 ses->auth_key.response = NULL;
5244 ses->auth_key.len = 0;
5245 }
5246
5247 if (server->ops->sess_setup)
5248 rc = server->ops->sess_setup(xid, ses, nls_info);
5249
5250 if (rc)
David Brazdil0f672f62019-12-10 10:32:29 +00005251 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00005252
5253 return rc;
5254}
5255
5256static int
5257cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
5258{
5259 vol->sectype = ses->sectype;
5260
5261 /* krb5 is special, since we don't need username or pw */
5262 if (vol->sectype == Kerberos)
5263 return 0;
5264
5265 return cifs_set_cifscreds(vol, ses);
5266}
5267
5268static struct cifs_tcon *
5269cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
5270{
5271 int rc;
5272 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
5273 struct cifs_ses *ses;
5274 struct cifs_tcon *tcon = NULL;
5275 struct smb_vol *vol_info;
5276
5277 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
5278 if (vol_info == NULL)
5279 return ERR_PTR(-ENOMEM);
5280
5281 vol_info->local_nls = cifs_sb->local_nls;
5282 vol_info->linux_uid = fsuid;
5283 vol_info->cred_uid = fsuid;
5284 vol_info->UNC = master_tcon->treeName;
5285 vol_info->retry = master_tcon->retry;
5286 vol_info->nocase = master_tcon->nocase;
5287 vol_info->nohandlecache = master_tcon->nohandlecache;
5288 vol_info->local_lease = master_tcon->local_lease;
Olivier Deprez0e641232021-09-23 10:07:05 +02005289 vol_info->no_lease = master_tcon->no_lease;
5290 vol_info->resilient = master_tcon->use_resilient;
5291 vol_info->persistent = master_tcon->use_persistent;
5292 vol_info->handle_timeout = master_tcon->handle_timeout;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00005293 vol_info->no_linux_ext = !master_tcon->unix_ext;
Olivier Deprez0e641232021-09-23 10:07:05 +02005294 vol_info->linux_ext = master_tcon->posix_extensions;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00005295 vol_info->sectype = master_tcon->ses->sectype;
5296 vol_info->sign = master_tcon->ses->sign;
Olivier Deprez0e641232021-09-23 10:07:05 +02005297 vol_info->seal = master_tcon->seal;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00005298
5299 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
5300 if (rc) {
5301 tcon = ERR_PTR(rc);
5302 goto out;
5303 }
5304
5305 /* get a reference for the same TCP session */
5306 spin_lock(&cifs_tcp_ses_lock);
5307 ++master_tcon->ses->server->srv_count;
5308 spin_unlock(&cifs_tcp_ses_lock);
5309
5310 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
5311 if (IS_ERR(ses)) {
5312 tcon = (struct cifs_tcon *)ses;
5313 cifs_put_tcp_session(master_tcon->ses->server, 0);
5314 goto out;
5315 }
5316
5317 tcon = cifs_get_tcon(ses, vol_info);
5318 if (IS_ERR(tcon)) {
5319 cifs_put_smb_ses(ses);
5320 goto out;
5321 }
5322
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00005323 if (cap_unix(ses))
5324 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
5325
5326out:
5327 kfree(vol_info->username);
5328 kzfree(vol_info->password);
5329 kfree(vol_info);
5330
5331 return tcon;
5332}
5333
5334struct cifs_tcon *
5335cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5336{
5337 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5338}
5339
5340/* find and return a tlink with given uid */
5341static struct tcon_link *
5342tlink_rb_search(struct rb_root *root, kuid_t uid)
5343{
5344 struct rb_node *node = root->rb_node;
5345 struct tcon_link *tlink;
5346
5347 while (node) {
5348 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5349
5350 if (uid_gt(tlink->tl_uid, uid))
5351 node = node->rb_left;
5352 else if (uid_lt(tlink->tl_uid, uid))
5353 node = node->rb_right;
5354 else
5355 return tlink;
5356 }
5357 return NULL;
5358}
5359
5360/* insert a tcon_link into the tree */
5361static void
5362tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5363{
5364 struct rb_node **new = &(root->rb_node), *parent = NULL;
5365 struct tcon_link *tlink;
5366
5367 while (*new) {
5368 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5369 parent = *new;
5370
5371 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
5372 new = &((*new)->rb_left);
5373 else
5374 new = &((*new)->rb_right);
5375 }
5376
5377 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5378 rb_insert_color(&new_tlink->tl_rbnode, root);
5379}
5380
5381/*
5382 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5383 * current task.
5384 *
5385 * If the superblock doesn't refer to a multiuser mount, then just return
5386 * the master tcon for the mount.
5387 *
5388 * First, search the rbtree for an existing tcon for this fsuid. If one
5389 * exists, then check to see if it's pending construction. If it is then wait
5390 * for construction to complete. Once it's no longer pending, check to see if
5391 * it failed and either return an error or retry construction, depending on
5392 * the timeout.
5393 *
5394 * If one doesn't exist then insert a new tcon_link struct into the tree and
5395 * try to construct a new one.
5396 */
5397struct tcon_link *
5398cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5399{
5400 int ret;
5401 kuid_t fsuid = current_fsuid();
5402 struct tcon_link *tlink, *newtlink;
5403
5404 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5405 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5406
5407 spin_lock(&cifs_sb->tlink_tree_lock);
5408 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
5409 if (tlink)
5410 cifs_get_tlink(tlink);
5411 spin_unlock(&cifs_sb->tlink_tree_lock);
5412
5413 if (tlink == NULL) {
5414 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5415 if (newtlink == NULL)
5416 return ERR_PTR(-ENOMEM);
5417 newtlink->tl_uid = fsuid;
5418 newtlink->tl_tcon = ERR_PTR(-EACCES);
5419 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5420 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5421 cifs_get_tlink(newtlink);
5422
5423 spin_lock(&cifs_sb->tlink_tree_lock);
5424 /* was one inserted after previous search? */
5425 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
5426 if (tlink) {
5427 cifs_get_tlink(tlink);
5428 spin_unlock(&cifs_sb->tlink_tree_lock);
5429 kfree(newtlink);
5430 goto wait_for_construction;
5431 }
5432 tlink = newtlink;
5433 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5434 spin_unlock(&cifs_sb->tlink_tree_lock);
5435 } else {
5436wait_for_construction:
5437 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
5438 TASK_INTERRUPTIBLE);
5439 if (ret) {
5440 cifs_put_tlink(tlink);
5441 return ERR_PTR(-ERESTARTSYS);
5442 }
5443
5444 /* if it's good, return it */
5445 if (!IS_ERR(tlink->tl_tcon))
5446 return tlink;
5447
5448 /* return error if we tried this already recently */
5449 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5450 cifs_put_tlink(tlink);
5451 return ERR_PTR(-EACCES);
5452 }
5453
5454 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5455 goto wait_for_construction;
5456 }
5457
5458 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5459 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5460 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5461
5462 if (IS_ERR(tlink->tl_tcon)) {
5463 cifs_put_tlink(tlink);
5464 return ERR_PTR(-EACCES);
5465 }
5466
5467 return tlink;
5468}
5469
5470/*
5471 * periodic workqueue job that scans tcon_tree for a superblock and closes
5472 * out tcons.
5473 */
5474static void
5475cifs_prune_tlinks(struct work_struct *work)
5476{
5477 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5478 prune_tlinks.work);
5479 struct rb_root *root = &cifs_sb->tlink_tree;
5480 struct rb_node *node;
5481 struct rb_node *tmp;
5482 struct tcon_link *tlink;
5483
5484 /*
5485 * Because we drop the spinlock in the loop in order to put the tlink
5486 * it's not guarded against removal of links from the tree. The only
5487 * places that remove entries from the tree are this function and
5488 * umounts. Because this function is non-reentrant and is canceled
5489 * before umount can proceed, this is safe.
5490 */
5491 spin_lock(&cifs_sb->tlink_tree_lock);
5492 node = rb_first(root);
5493 while (node != NULL) {
5494 tmp = node;
5495 node = rb_next(tmp);
5496 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5497
5498 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5499 atomic_read(&tlink->tl_count) != 0 ||
5500 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5501 continue;
5502
5503 cifs_get_tlink(tlink);
5504 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5505 rb_erase(tmp, root);
5506
5507 spin_unlock(&cifs_sb->tlink_tree_lock);
5508 cifs_put_tlink(tlink);
5509 spin_lock(&cifs_sb->tlink_tree_lock);
5510 }
5511 spin_unlock(&cifs_sb->tlink_tree_lock);
5512
5513 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
5514 TLINK_IDLE_EXPIRE);
5515}