blob: b807f8a78adc8b8b80cca1ba7a9445fe68f840d1 [file] [log] [blame]
Ronnie Sahlberga6a9cff2020-10-21 10:22:33 +10001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2020, Microsoft Corporation.
4 *
5 * Author(s): Steve French <stfrench@microsoft.com>
6 * David Howells <dhowells@redhat.com>
7 */
8
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06009/*
10#include <linux/module.h>
11#include <linux/nsproxy.h>
12#include <linux/slab.h>
13#include <linux/magic.h>
14#include <linux/security.h>
15#include <net/net_namespace.h>
16*/
17
18#include <linux/ctype.h>
19#include <linux/fs_context.h>
20#include <linux/fs_parser.h>
21#include <linux/fs.h>
22#include <linux/mount.h>
23#include <linux/parser.h>
24#include <linux/utsname.h>
25#include "cifsfs.h"
26#include "cifspdu.h"
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100027#include "cifsglob.h"
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +100028#include "cifsproto.h"
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -060029#include "cifs_unicode.h"
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100030#include "cifs_debug.h"
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -060031#include "cifs_fs_sb.h"
32#include "ntlmssp.h"
33#include "nterr.h"
34#include "rfc1002pdu.h"
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100035#include "fs_context.h"
36
Ronnie Sahlberg555782a2020-10-21 12:10:44 +100037static const match_table_t cifs_smb_version_tokens = {
38 { Smb_1, SMB1_VERSION_STRING },
39 { Smb_20, SMB20_VERSION_STRING},
40 { Smb_21, SMB21_VERSION_STRING },
41 { Smb_30, SMB30_VERSION_STRING },
42 { Smb_302, SMB302_VERSION_STRING },
43 { Smb_302, ALT_SMB302_VERSION_STRING },
44 { Smb_311, SMB311_VERSION_STRING },
45 { Smb_311, ALT_SMB311_VERSION_STRING },
46 { Smb_3any, SMB3ANY_VERSION_STRING },
47 { Smb_default, SMBDEFAULT_VERSION_STRING },
48 { Smb_version_err, NULL }
49};
50
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100051static const match_table_t cifs_secflavor_tokens = {
52 { Opt_sec_krb5, "krb5" },
53 { Opt_sec_krb5i, "krb5i" },
54 { Opt_sec_krb5p, "krb5p" },
55 { Opt_sec_ntlmsspi, "ntlmsspi" },
56 { Opt_sec_ntlmssp, "ntlmssp" },
57 { Opt_ntlm, "ntlm" },
58 { Opt_sec_ntlmi, "ntlmi" },
59 { Opt_sec_ntlmv2, "nontlm" },
60 { Opt_sec_ntlmv2, "ntlmv2" },
61 { Opt_sec_ntlmv2i, "ntlmv2i" },
62 { Opt_sec_lanman, "lanman" },
63 { Opt_sec_none, "none" },
64
65 { Opt_sec_err, NULL }
66};
67
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -060068const struct fs_parameter_spec smb3_fs_parameters[] = {
69 /* Mount options that take no arguments */
70 fsparam_flag_no("user_xattr", Opt_user_xattr),
71 fsparam_flag_no("forceuid", Opt_forceuid),
72 fsparam_flag_no("multichannel", Opt_multichannel),
73 fsparam_flag_no("forcegid", Opt_forcegid),
74 fsparam_flag("noblocksend", Opt_noblocksend),
75 fsparam_flag("noautotune", Opt_noautotune),
76 fsparam_flag("nolease", Opt_nolease),
77 fsparam_flag_no("hard", Opt_hard),
78 fsparam_flag_no("soft", Opt_soft),
79 fsparam_flag_no("perm", Opt_perm),
80 fsparam_flag("nodelete", Opt_nodelete),
81 fsparam_flag_no("mapposix", Opt_mapposix),
82 fsparam_flag("mapchars", Opt_mapchars),
83 fsparam_flag("nomapchars", Opt_nomapchars),
84 fsparam_flag_no("sfu", Opt_sfu),
85 fsparam_flag("nodfs", Opt_nodfs),
86 fsparam_flag_no("posixpaths", Opt_posixpaths),
87 fsparam_flag_no("unix", Opt_unix),
88 fsparam_flag_no("linux", Opt_unix),
89 fsparam_flag_no("posix", Opt_unix),
90 fsparam_flag("nocase", Opt_nocase),
91 fsparam_flag("ignorecase", Opt_nocase),
92 fsparam_flag_no("brl", Opt_brl),
93 fsparam_flag_no("handlecache", Opt_handlecache),
94 fsparam_flag("forcemandatorylock", Opt_forcemandatorylock),
95 fsparam_flag("forcemand", Opt_forcemandatorylock),
96 fsparam_flag("setuidfromacl", Opt_setuidfromacl),
97 fsparam_flag_no("setuids", Opt_setuids),
98 fsparam_flag_no("dynperm", Opt_dynperm),
99 fsparam_flag_no("intr", Opt_intr),
100 fsparam_flag_no("strictsync", Opt_strictsync),
101 fsparam_flag_no("serverino", Opt_serverino),
102 fsparam_flag("rwpidforward", Opt_rwpidforward),
103 fsparam_flag("cifsacl", Opt_cifsacl),
104 fsparam_flag_no("acl", Opt_acl),
105 fsparam_flag("locallease", Opt_locallease),
106 fsparam_flag("sign", Opt_sign),
107 fsparam_flag("ignore_signature", Opt_ignore_signature),
108 fsparam_flag("seal", Opt_seal),
109 fsparam_flag("noac", Opt_noac),
110 fsparam_flag("fsc", Opt_fsc),
111 fsparam_flag("mfsymlinks", Opt_mfsymlinks),
112 fsparam_flag("multiuser", Opt_multiuser),
113 fsparam_flag("sloppy", Opt_sloppy),
114 fsparam_flag("nosharesock", Opt_nosharesock),
115 fsparam_flag_no("persistent", Opt_persistent),
116 fsparam_flag_no("resilient", Opt_resilient),
117 fsparam_flag("domainauto", Opt_domainauto),
118 fsparam_flag("rdma", Opt_rdma),
119 fsparam_flag("modesid", Opt_modesid),
120 fsparam_flag("rootfs", Opt_rootfs),
121 fsparam_flag("compress", Opt_compress),
Samuel Cabrero0ac4e292020-12-11 22:59:29 -0600122 fsparam_flag("witness", Opt_witness),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600123
124 /* Mount options which take numeric value */
125 fsparam_u32("backupuid", Opt_backupuid),
126 fsparam_u32("backupgid", Opt_backupgid),
127 fsparam_u32("uid", Opt_uid),
128 fsparam_u32("cruid", Opt_cruid),
129 fsparam_u32("gid", Opt_gid),
130 fsparam_u32("file_mode", Opt_file_mode),
131 fsparam_u32("dirmode", Opt_dirmode),
132 fsparam_u32("dir_mode", Opt_dirmode),
133 fsparam_u32("port", Opt_port),
134 fsparam_u32("min_enc_offload", Opt_min_enc_offload),
135 fsparam_u32("bsize", Opt_blocksize),
136 fsparam_u32("rsize", Opt_rsize),
137 fsparam_u32("wsize", Opt_wsize),
138 fsparam_u32("actimeo", Opt_actimeo),
139 fsparam_u32("echo_interval", Opt_echo_interval),
140 fsparam_u32("max_credits", Opt_max_credits),
141 fsparam_u32("handletimeout", Opt_handletimeout),
142 fsparam_u32("snapshot", Opt_snapshot),
143 fsparam_u32("max_channels", Opt_max_channels),
144
145 /* Mount options which take string value */
146 fsparam_string("source", Opt_source),
147 fsparam_string("unc", Opt_source),
148 fsparam_string("user", Opt_user),
149 fsparam_string("username", Opt_user),
150 fsparam_string("pass", Opt_pass),
151 fsparam_string("password", Opt_pass),
152 fsparam_string("ip", Opt_ip),
153 fsparam_string("addr", Opt_ip),
154 fsparam_string("domain", Opt_domain),
155 fsparam_string("dom", Opt_domain),
156 fsparam_string("srcaddr", Opt_srcaddr),
157 fsparam_string("iocharset", Opt_iocharset),
158 fsparam_string("netbiosname", Opt_netbiosname),
159 fsparam_string("servern", Opt_servern),
160 fsparam_string("ver", Opt_ver),
161 fsparam_string("vers", Opt_vers),
162 fsparam_string("sec", Opt_sec),
163 fsparam_string("cache", Opt_cache),
164
165 /* Arguments that should be ignored */
166 fsparam_flag("guest", Opt_ignore),
167 fsparam_flag("noatime", Opt_ignore),
168 fsparam_flag("relatime", Opt_ignore),
169 fsparam_flag("_netdev", Opt_ignore),
170 fsparam_flag_no("suid", Opt_ignore),
171 fsparam_flag_no("exec", Opt_ignore),
172 fsparam_flag_no("dev", Opt_ignore),
173 fsparam_flag_no("mand", Opt_ignore),
174 fsparam_string("cred", Opt_ignore),
175 fsparam_string("credentials", Opt_ignore),
Dmitry Osipenko427c4f02020-12-14 14:37:45 +0300176 {}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600177};
178
179int
180cifs_parse_security_flavors(char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000181{
182
183 substring_t args[MAX_OPT_ARGS];
184
185 /*
186 * With mount options, the last one should win. Reset any existing
187 * settings back to default.
188 */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600189 ctx->sectype = Unspecified;
190 ctx->sign = false;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000191
192 switch (match_token(value, cifs_secflavor_tokens, args)) {
193 case Opt_sec_krb5p:
194 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
195 return 1;
196 case Opt_sec_krb5i:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600197 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000198 fallthrough;
199 case Opt_sec_krb5:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600200 ctx->sectype = Kerberos;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000201 break;
202 case Opt_sec_ntlmsspi:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600203 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000204 fallthrough;
205 case Opt_sec_ntlmssp:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600206 ctx->sectype = RawNTLMSSP;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000207 break;
208 case Opt_sec_ntlmi:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600209 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000210 fallthrough;
211 case Opt_ntlm:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600212 ctx->sectype = NTLM;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000213 break;
214 case Opt_sec_ntlmv2i:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600215 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000216 fallthrough;
217 case Opt_sec_ntlmv2:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600218 ctx->sectype = NTLMv2;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000219 break;
220#ifdef CONFIG_CIFS_WEAK_PW_HASH
221 case Opt_sec_lanman:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600222 ctx->sectype = LANMAN;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000223 break;
224#endif
225 case Opt_sec_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600226 ctx->nullauth = 1;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000227 break;
228 default:
229 cifs_dbg(VFS, "bad security option: %s\n", value);
230 return 1;
231 }
232
233 return 0;
234}
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000235
236static const match_table_t cifs_cacheflavor_tokens = {
237 { Opt_cache_loose, "loose" },
238 { Opt_cache_strict, "strict" },
239 { Opt_cache_none, "none" },
240 { Opt_cache_ro, "ro" },
241 { Opt_cache_rw, "singleclient" },
242 { Opt_cache_err, NULL }
243};
244
245int
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600246cifs_parse_cache_flavor(char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000247{
248 substring_t args[MAX_OPT_ARGS];
249
250 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
251 case Opt_cache_loose:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600252 ctx->direct_io = false;
253 ctx->strict_io = false;
254 ctx->cache_ro = false;
255 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000256 break;
257 case Opt_cache_strict:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600258 ctx->direct_io = false;
259 ctx->strict_io = true;
260 ctx->cache_ro = false;
261 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000262 break;
263 case Opt_cache_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600264 ctx->direct_io = true;
265 ctx->strict_io = false;
266 ctx->cache_ro = false;
267 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000268 break;
269 case Opt_cache_ro:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600270 ctx->direct_io = false;
271 ctx->strict_io = false;
272 ctx->cache_ro = true;
273 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000274 break;
275 case Opt_cache_rw:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600276 ctx->direct_io = false;
277 ctx->strict_io = false;
278 ctx->cache_ro = false;
279 ctx->cache_rw = true;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000280 break;
281 default:
282 cifs_dbg(VFS, "bad cache= option: %s\n", value);
283 return 1;
284 }
285 return 0;
286}
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000287
288#define DUP_CTX_STR(field) \
289do { \
290 if (ctx->field) { \
291 new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC); \
292 if (new_ctx->field == NULL) { \
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000293 smb3_cleanup_fs_context_contents(new_ctx); \
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000294 return -ENOMEM; \
295 } \
296 } \
297} while (0)
298
299int
300smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)
301{
302 int rc = 0;
303
304 memcpy(new_ctx, ctx, sizeof(*ctx));
305 new_ctx->prepath = NULL;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600306 new_ctx->mount_options = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000307 new_ctx->local_nls = NULL;
308 new_ctx->nodename = NULL;
309 new_ctx->username = NULL;
310 new_ctx->password = NULL;
311 new_ctx->domainname = NULL;
312 new_ctx->UNC = NULL;
313 new_ctx->iocharset = NULL;
314
315 /*
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000316 * Make sure to stay in sync with smb3_cleanup_fs_context_contents()
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000317 */
318 DUP_CTX_STR(prepath);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600319 DUP_CTX_STR(mount_options);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000320 DUP_CTX_STR(username);
321 DUP_CTX_STR(password);
322 DUP_CTX_STR(UNC);
323 DUP_CTX_STR(domainname);
324 DUP_CTX_STR(nodename);
325 DUP_CTX_STR(iocharset);
326
327 return rc;
328}
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000329
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600330static int
331cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3)
332{
333 substring_t args[MAX_OPT_ARGS];
334
335 switch (match_token(value, cifs_smb_version_tokens, args)) {
336#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
337 case Smb_1:
338 if (disable_legacy_dialects) {
339 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
340 return 1;
341 }
342 if (is_smb3) {
343 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
344 return 1;
345 }
346 cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
347 ctx->ops = &smb1_operations;
348 ctx->vals = &smb1_values;
349 break;
350 case Smb_20:
351 if (disable_legacy_dialects) {
352 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
353 return 1;
354 }
355 if (is_smb3) {
356 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
357 return 1;
358 }
359 ctx->ops = &smb20_operations;
360 ctx->vals = &smb20_values;
361 break;
362#else
363 case Smb_1:
364 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
365 return 1;
366 case Smb_20:
367 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
368 return 1;
369#endif /* CIFS_ALLOW_INSECURE_LEGACY */
370 case Smb_21:
371 ctx->ops = &smb21_operations;
372 ctx->vals = &smb21_values;
373 break;
374 case Smb_30:
375 ctx->ops = &smb30_operations;
376 ctx->vals = &smb30_values;
377 break;
378 case Smb_302:
379 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
380 ctx->vals = &smb302_values;
381 break;
382 case Smb_311:
383 ctx->ops = &smb311_operations;
384 ctx->vals = &smb311_values;
385 break;
386 case Smb_3any:
387 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
388 ctx->vals = &smb3any_values;
389 break;
390 case Smb_default:
391 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
392 ctx->vals = &smbdefault_values;
393 break;
394 default:
395 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
396 return 1;
397 }
398 return 0;
399}
400
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000401/*
402 * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath
403 * fields with the result. Returns 0 on success and an error otherwise
404 * (e.g. ENOMEM or EINVAL)
405 */
406int
407smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
408{
409 char *pos;
410 const char *delims = "/\\";
411 size_t len;
412
413 if (unlikely(!devname || !*devname)) {
414 cifs_dbg(VFS, "Device name not specified\n");
415 return -EINVAL;
416 }
417
418 /* make sure we have a valid UNC double delimiter prefix */
419 len = strspn(devname, delims);
420 if (len != 2)
421 return -EINVAL;
422
423 /* find delimiter between host and sharename */
424 pos = strpbrk(devname + 2, delims);
425 if (!pos)
426 return -EINVAL;
427
428 /* skip past delimiter */
429 ++pos;
430
431 /* now go until next delimiter or end of string */
432 len = strcspn(pos, delims);
433
434 /* move "pos" up to delimiter or NULL */
435 pos += len;
436 ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
437 if (!ctx->UNC)
438 return -ENOMEM;
439
440 convert_delimiter(ctx->UNC, '\\');
441
442 /* skip any delimiter */
443 if (*pos == '/' || *pos == '\\')
444 pos++;
445
446 /* If pos is NULL then no prepath */
447 if (!*pos)
448 return 0;
449
450 ctx->prepath = kstrdup(pos, GFP_KERNEL);
451 if (!ctx->prepath)
452 return -ENOMEM;
453
454 return 0;
455}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600456
457static void smb3_fs_context_free(struct fs_context *fc);
458static int smb3_fs_context_parse_param(struct fs_context *fc,
459 struct fs_parameter *param);
460static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
461 void *data);
462static int smb3_get_tree(struct fs_context *fc);
463static int smb3_reconfigure(struct fs_context *fc);
464
465static const struct fs_context_operations smb3_fs_context_ops = {
466 .free = smb3_fs_context_free,
467 .parse_param = smb3_fs_context_parse_param,
468 .parse_monolithic = smb3_fs_context_parse_monolithic,
469 .get_tree = smb3_get_tree,
470 .reconfigure = smb3_reconfigure,
471};
472
473/*
474 * Parse a monolithic block of data from sys_mount().
475 * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data
476 * @ctx: The superblock configuration to fill in.
477 * @data: The data to parse
478 *
479 * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be
480 * called from the ->monolithic_mount_data() fs_context operation.
481 *
482 * Returns 0 on success or the error returned by the ->parse_option() fs_context
483 * operation on failure.
484 */
485static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
486 void *data)
487{
488 struct smb3_fs_context *ctx = smb3_fc2context(fc);
489 char *options = data, *key;
490 int ret = 0;
491
492 if (!options)
493 return 0;
494
495 ctx->mount_options = kstrdup(data, GFP_KERNEL);
496 if (ctx->mount_options == NULL)
497 return -ENOMEM;
498
499 ret = security_sb_eat_lsm_opts(options, &fc->security);
500 if (ret)
501 return ret;
502
503 /* BB Need to add support for sep= here TBD */
504 while ((key = strsep(&options, ",")) != NULL) {
505 if (*key) {
506 size_t v_len = 0;
507 char *value = strchr(key, '=');
508
509 if (value) {
510 if (value == key)
511 continue;
512 *value++ = 0;
513 v_len = strlen(value);
514 }
515 ret = vfs_parse_fs_string(fc, key, value, v_len);
516 if (ret < 0)
517 break;
518 }
519 }
520
521 return ret;
522}
523
524/*
525 * Validate the preparsed information in the config.
526 */
527static int smb3_fs_context_validate(struct fs_context *fc)
528{
529 struct smb3_fs_context *ctx = smb3_fc2context(fc);
530
531 if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
532 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
533 return -1;
534 }
535
536#ifndef CONFIG_KEYS
537 /* Muliuser mounts require CONFIG_KEYS support */
538 if (ctx->multiuser) {
539 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
540 return -1;
541 }
542#endif
543
544 if (ctx->got_version == false)
545 pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n");
546
547
548 if (!ctx->UNC) {
549 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
550 return -1;
551 }
552
553 /* make sure UNC has a share name */
554 if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
555 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
556 return -1;
557 }
558
559 if (!ctx->got_ip) {
560 int len;
561 const char *slash;
562
563 /* No ip= option specified? Try to get it from UNC */
564 /* Use the address part of the UNC. */
565 slash = strchr(&ctx->UNC[2], '\\');
566 len = slash - &ctx->UNC[2];
567 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
568 &ctx->UNC[2], len)) {
569 pr_err("Unable to determine destination address\n");
570 return -1;
571 }
572 }
573
574 /* set the port that we got earlier */
575 cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
576
577 if (ctx->override_uid && !ctx->uid_specified) {
578 ctx->override_uid = 0;
579 pr_notice("ignoring forceuid mount option specified with no uid= option\n");
580 }
581
582 if (ctx->override_gid && !ctx->gid_specified) {
583 ctx->override_gid = 0;
584 pr_notice("ignoring forcegid mount option specified with no gid= option\n");
585 }
586
587 return 0;
588}
589
590static int smb3_get_tree_common(struct fs_context *fc)
591{
592 struct smb3_fs_context *ctx = smb3_fc2context(fc);
593 struct dentry *root;
594 int rc = 0;
595
596 root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);
597 if (IS_ERR(root))
598 return PTR_ERR(root);
599
600 fc->root = root;
601
602 return rc;
603}
604
605/*
606 * Create an SMB3 superblock from the parameters passed.
607 */
608static int smb3_get_tree(struct fs_context *fc)
609{
610 int err = smb3_fs_context_validate(fc);
611
612 if (err)
613 return err;
614 return smb3_get_tree_common(fc);
615}
616
617static void smb3_fs_context_free(struct fs_context *fc)
618{
619 struct smb3_fs_context *ctx = smb3_fc2context(fc);
620
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000621 smb3_cleanup_fs_context(ctx);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600622}
623
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000624/*
625 * Compare the old and new proposed context during reconfigure
626 * and check if the changes are compatible.
627 */
628static int smb3_verify_reconfigure_ctx(struct smb3_fs_context *new_ctx,
629 struct smb3_fs_context *old_ctx)
630{
631 if (new_ctx->sectype != old_ctx->sectype) {
632 cifs_dbg(VFS, "can not change sec during remount\n");
633 return -EINVAL;
634 }
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000635 if (new_ctx->multiuser != old_ctx->multiuser) {
636 cifs_dbg(VFS, "can not change multiuser during remount\n");
637 return -EINVAL;
638 }
639 if (new_ctx->UNC &&
640 (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {
641 cifs_dbg(VFS, "can not change UNC during remount\n");
642 return -EINVAL;
643 }
644 if (new_ctx->username &&
645 (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {
646 cifs_dbg(VFS, "can not change username during remount\n");
647 return -EINVAL;
648 }
649 if (new_ctx->password &&
650 (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
651 cifs_dbg(VFS, "can not change password during remount\n");
652 return -EINVAL;
653 }
654 if (new_ctx->domainname &&
655 (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
656 cifs_dbg(VFS, "can not change domainname during remount\n");
657 return -EINVAL;
658 }
659 if (new_ctx->nodename &&
660 (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
661 cifs_dbg(VFS, "can not change nodename during remount\n");
662 return -EINVAL;
663 }
664 if (new_ctx->iocharset &&
665 (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {
666 cifs_dbg(VFS, "can not change iocharset during remount\n");
667 return -EINVAL;
668 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000669
670 return 0;
671}
672
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000673#define STEAL_STRING(cifs_sb, ctx, field) \
674do { \
675 kfree(ctx->field); \
676 ctx->field = cifs_sb->ctx->field; \
677 cifs_sb->ctx->field = NULL; \
678} while (0)
679
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600680static int smb3_reconfigure(struct fs_context *fc)
681{
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000682 struct smb3_fs_context *ctx = smb3_fc2context(fc);
683 struct dentry *root = fc->root;
684 struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
685 int rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600686
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000687 rc = smb3_verify_reconfigure_ctx(ctx, cifs_sb->ctx);
688 if (rc)
689 return rc;
690
691 /*
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000692 * We can not change UNC/username/password/domainname/nodename/iocharset
693 * during reconnect so ignore what we have in the new context and
694 * just use what we already have in cifs_sb->ctx.
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000695 */
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000696 STEAL_STRING(cifs_sb, ctx, UNC);
697 STEAL_STRING(cifs_sb, ctx, username);
698 STEAL_STRING(cifs_sb, ctx, password);
699 STEAL_STRING(cifs_sb, ctx, domainname);
700 STEAL_STRING(cifs_sb, ctx, nodename);
701 STEAL_STRING(cifs_sb, ctx, iocharset);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000702
703 smb3_cleanup_fs_context_contents(cifs_sb->ctx);
704 rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
705
706 return rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600707}
708
709static int smb3_fs_context_parse_param(struct fs_context *fc,
710 struct fs_parameter *param)
711{
712 struct fs_parse_result result;
713 struct smb3_fs_context *ctx = smb3_fc2context(fc);
714 int i, opt;
715 bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
716 bool skip_parsing = false;
717
718 cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
719
720 /*
721 * fs_parse can not handle string options with an empty value so
722 * we will need special handling of them.
723 */
724 if (param->type == fs_value_is_string && param->string[0] == 0) {
725 if (!strcmp("pass", param->key) || !strcmp("password", param->key))
726 skip_parsing = true;
727 }
728
729 if (!skip_parsing) {
730 opt = fs_parse(fc, smb3_fs_parameters, param, &result);
731 if (opt < 0)
732 return ctx->sloppy ? 1 : opt;
733 }
734
735 switch (opt) {
736 case Opt_compress:
737 ctx->compression = UNKNOWN_TYPE;
738 cifs_dbg(VFS,
739 "SMB3 compression support is experimental\n");
740 break;
741 case Opt_nodfs:
742 ctx->nodfs = 1;
743 break;
744 case Opt_hard:
745 if (result.negated)
746 ctx->retry = 0;
747 else
748 ctx->retry = 1;
749 break;
750 case Opt_soft:
751 if (result.negated)
752 ctx->retry = 1;
753 else
754 ctx->retry = 0;
755 break;
756 case Opt_mapposix:
757 if (result.negated)
758 ctx->remap = false;
759 else {
760 ctx->remap = true;
761 ctx->sfu_remap = false; /* disable SFU mapping */
762 }
763 break;
764 case Opt_user_xattr:
765 if (result.negated)
766 ctx->no_xattr = 1;
767 else
768 ctx->no_xattr = 0;
769 break;
770 case Opt_forceuid:
771 if (result.negated)
772 ctx->override_uid = 0;
773 else
774 ctx->override_uid = 1;
775 break;
776 case Opt_forcegid:
777 if (result.negated)
778 ctx->override_gid = 0;
779 else
780 ctx->override_gid = 1;
781 break;
782 case Opt_perm:
783 if (result.negated)
784 ctx->noperm = 1;
785 else
786 ctx->noperm = 0;
787 break;
788 case Opt_dynperm:
789 if (result.negated)
790 ctx->dynperm = 0;
791 else
792 ctx->dynperm = 1;
793 break;
794 case Opt_sfu:
795 if (result.negated)
796 ctx->sfu_emul = 0;
797 else
798 ctx->sfu_emul = 1;
799 break;
800 case Opt_noblocksend:
801 ctx->noblocksnd = 1;
802 break;
803 case Opt_noautotune:
804 ctx->noautotune = 1;
805 break;
806 case Opt_nolease:
807 ctx->no_lease = 1;
808 break;
809 case Opt_nodelete:
810 ctx->nodelete = 1;
811 break;
812 case Opt_multichannel:
813 if (result.negated) {
814 ctx->multichannel = false;
815 ctx->max_channels = 1;
816 } else {
817 ctx->multichannel = true;
818 /* if number of channels not specified, default to 2 */
819 if (ctx->max_channels < 2)
820 ctx->max_channels = 2;
821 }
822 break;
823 case Opt_uid:
824 ctx->linux_uid.val = result.uint_32;
825 ctx->uid_specified = true;
826 break;
827 case Opt_cruid:
828 ctx->cred_uid.val = result.uint_32;
829 break;
830 case Opt_backupgid:
831 ctx->backupgid.val = result.uint_32;
832 ctx->backupgid_specified = true;
833 break;
834 case Opt_gid:
835 ctx->linux_gid.val = result.uint_32;
836 ctx->gid_specified = true;
837 break;
838 case Opt_port:
839 ctx->port = result.uint_32;
840 break;
841 case Opt_file_mode:
842 ctx->file_mode = result.uint_32;
843 break;
844 case Opt_dirmode:
845 ctx->dir_mode = result.uint_32;
846 break;
847 case Opt_min_enc_offload:
848 ctx->min_offload = result.uint_32;
849 break;
850 case Opt_blocksize:
851 /*
852 * inode blocksize realistically should never need to be
853 * less than 16K or greater than 16M and default is 1MB.
854 * Note that small inode block sizes (e.g. 64K) can lead
855 * to very poor performance of common tools like cp and scp
856 */
857 if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||
858 (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {
859 cifs_dbg(VFS, "%s: Invalid blocksize\n",
860 __func__);
861 goto cifs_parse_mount_err;
862 }
863 ctx->bsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000864 ctx->got_bsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600865 break;
866 case Opt_rsize:
867 ctx->rsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000868 ctx->got_rsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600869 break;
870 case Opt_wsize:
871 ctx->wsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000872 ctx->got_wsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600873 break;
874 case Opt_actimeo:
875 ctx->actimeo = HZ * result.uint_32;
876 if (ctx->actimeo > CIFS_MAX_ACTIMEO) {
877 cifs_dbg(VFS, "attribute cache timeout too large\n");
878 goto cifs_parse_mount_err;
879 }
880 break;
881 case Opt_echo_interval:
882 ctx->echo_interval = result.uint_32;
883 break;
884 case Opt_snapshot:
885 ctx->snapshot_time = result.uint_32;
886 break;
887 case Opt_max_credits:
888 if (result.uint_32 < 20 || result.uint_32 > 60000) {
889 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
890 __func__);
891 goto cifs_parse_mount_err;
892 }
893 ctx->max_credits = result.uint_32;
894 break;
895 case Opt_max_channels:
896 if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {
897 cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
898 __func__, CIFS_MAX_CHANNELS);
899 goto cifs_parse_mount_err;
900 }
901 ctx->max_channels = result.uint_32;
902 break;
903 case Opt_handletimeout:
904 ctx->handle_timeout = result.uint_32;
905 if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
906 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
907 goto cifs_parse_mount_err;
908 }
909 break;
910 case Opt_source:
911 kfree(ctx->UNC);
912 ctx->UNC = NULL;
913 switch (smb3_parse_devname(param->string, ctx)) {
914 case 0:
915 break;
916 case -ENOMEM:
917 cifs_dbg(VFS, "Unable to allocate memory for devname\n");
918 goto cifs_parse_mount_err;
919 case -EINVAL:
920 cifs_dbg(VFS, "Malformed UNC in devname\n");
921 goto cifs_parse_mount_err;
922 default:
923 cifs_dbg(VFS, "Unknown error parsing devname\n");
924 goto cifs_parse_mount_err;
925 }
926 fc->source = kstrdup(param->string, GFP_KERNEL);
927 if (fc->source == NULL) {
928 cifs_dbg(VFS, "OOM when copying UNC string\n");
929 goto cifs_parse_mount_err;
930 }
931 break;
932 case Opt_user:
933 kfree(ctx->username);
934 ctx->username = NULL;
935 if (strlen(param->string) == 0) {
936 /* null user, ie. anonymous authentication */
937 ctx->nullauth = 1;
938 break;
939 }
940
941 if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) >
942 CIFS_MAX_USERNAME_LEN) {
943 pr_warn("username too long\n");
944 goto cifs_parse_mount_err;
945 }
946 ctx->username = kstrdup(param->string, GFP_KERNEL);
947 if (ctx->username == NULL) {
948 cifs_dbg(VFS, "OOM when copying username string\n");
949 goto cifs_parse_mount_err;
950 }
951 break;
952 case Opt_pass:
953 kfree(ctx->password);
954 ctx->password = NULL;
955 if (strlen(param->string) == 0)
956 break;
957
958 ctx->password = kstrdup(param->string, GFP_KERNEL);
959 if (ctx->password == NULL) {
960 cifs_dbg(VFS, "OOM when copying password string\n");
961 goto cifs_parse_mount_err;
962 }
963 break;
964 case Opt_ip:
965 if (strlen(param->string) == 0) {
966 ctx->got_ip = false;
967 break;
968 }
969 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
970 param->string,
971 strlen(param->string))) {
972 pr_err("bad ip= option (%s)\n", param->string);
973 goto cifs_parse_mount_err;
974 }
975 ctx->got_ip = true;
976 break;
977 case Opt_domain:
978 if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN)
979 == CIFS_MAX_DOMAINNAME_LEN) {
980 pr_warn("domain name too long\n");
981 goto cifs_parse_mount_err;
982 }
983
984 kfree(ctx->domainname);
985 ctx->domainname = kstrdup(param->string, GFP_KERNEL);
986 if (ctx->domainname == NULL) {
987 cifs_dbg(VFS, "OOM when copying domainname string\n");
988 goto cifs_parse_mount_err;
989 }
990 cifs_dbg(FYI, "Domain name set\n");
991 break;
992 case Opt_srcaddr:
993 if (!cifs_convert_address(
994 (struct sockaddr *)&ctx->srcaddr,
995 param->string, strlen(param->string))) {
996 pr_warn("Could not parse srcaddr: %s\n",
997 param->string);
998 goto cifs_parse_mount_err;
999 }
1000 break;
1001 case Opt_iocharset:
1002 if (strnlen(param->string, 1024) >= 65) {
1003 pr_warn("iocharset name too long\n");
1004 goto cifs_parse_mount_err;
1005 }
1006
1007 if (strncasecmp(param->string, "default", 7) != 0) {
1008 kfree(ctx->iocharset);
1009 ctx->iocharset = kstrdup(param->string, GFP_KERNEL);
1010 if (ctx->iocharset == NULL) {
1011 cifs_dbg(VFS, "OOM when copying iocharset string\n");
1012 goto cifs_parse_mount_err;
1013 }
1014 }
1015 /* if iocharset not set then load_nls_default
1016 * is used by caller
1017 */
1018 cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
1019 break;
1020 case Opt_netbiosname:
1021 memset(ctx->source_rfc1001_name, 0x20,
1022 RFC1001_NAME_LEN);
1023 /*
1024 * FIXME: are there cases in which a comma can
1025 * be valid in workstation netbios name (and
1026 * need special handling)?
1027 */
1028 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1029 /* don't ucase netbiosname for user */
1030 if (param->string[i] == 0)
1031 break;
1032 ctx->source_rfc1001_name[i] = param->string[i];
1033 }
1034 /* The string has 16th byte zero still from
1035 * set at top of the function
1036 */
1037 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1038 pr_warn("netbiosname longer than 15 truncated\n");
1039 break;
1040 case Opt_servern:
1041 /* last byte, type, is 0x20 for servr type */
1042 memset(ctx->target_rfc1001_name, 0x20,
1043 RFC1001_NAME_LEN_WITH_NULL);
1044 /*
1045 * BB are there cases in which a comma can be valid in this
1046 * workstation netbios name (and need special handling)?
1047 */
1048
1049 /* user or mount helper must uppercase the netbios name */
1050 for (i = 0; i < 15; i++) {
1051 if (param->string[i] == 0)
1052 break;
1053 ctx->target_rfc1001_name[i] = param->string[i];
1054 }
1055
1056 /* The string has 16th byte zero still from set at top of function */
1057 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1058 pr_warn("server netbiosname longer than 15 truncated\n");
1059 break;
1060 case Opt_ver:
1061 /* version of mount userspace tools, not dialect */
1062 /* If interface changes in mount.cifs bump to new ver */
1063 if (strncasecmp(param->string, "1", 1) == 0) {
1064 if (strlen(param->string) > 1) {
1065 pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
1066 param->string);
1067 goto cifs_parse_mount_err;
1068 }
1069 /* This is the default */
1070 break;
1071 }
1072 /* For all other value, error */
1073 pr_warn("Invalid mount helper version specified\n");
1074 goto cifs_parse_mount_err;
1075 case Opt_vers:
1076 /* protocol version (dialect) */
1077 if (cifs_parse_smb_version(param->string, ctx, is_smb3) != 0)
1078 goto cifs_parse_mount_err;
1079 ctx->got_version = true;
1080 break;
1081 case Opt_sec:
1082 if (cifs_parse_security_flavors(param->string, ctx) != 0)
1083 goto cifs_parse_mount_err;
1084 break;
1085 case Opt_cache:
1086 if (cifs_parse_cache_flavor(param->string, ctx) != 0)
1087 goto cifs_parse_mount_err;
1088 break;
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001089 case Opt_witness:
1090#ifndef CONFIG_CIFS_SWN_UPCALL
1091 cifs_dbg(VFS, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
1092 goto cifs_parse_mount_err;
1093#endif
1094 ctx->witness = true;
1095 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001096 case Opt_rootfs:
1097#ifdef CONFIG_CIFS_ROOT
1098 ctx->rootfs = true;
1099#endif
1100 break;
1101 case Opt_posixpaths:
1102 if (result.negated)
1103 ctx->posix_paths = 0;
1104 else
1105 ctx->posix_paths = 1;
1106 break;
1107 case Opt_unix:
1108 if (result.negated)
1109 ctx->linux_ext = 0;
1110 else
1111 ctx->no_linux_ext = 1;
1112 break;
1113 case Opt_nocase:
1114 ctx->nocase = 1;
1115 break;
1116 case Opt_brl:
1117 if (result.negated) {
1118 /*
1119 * turn off mandatory locking in mode
1120 * if remote locking is turned off since the
1121 * local vfs will do advisory
1122 */
1123 if (ctx->file_mode ==
1124 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1125 ctx->file_mode = S_IALLUGO;
1126 ctx->nobrl = 1;
1127 } else
1128 ctx->nobrl = 0;
1129 break;
1130 case Opt_handlecache:
1131 if (result.negated)
1132 ctx->nohandlecache = 1;
1133 else
1134 ctx->nohandlecache = 0;
1135 break;
1136 case Opt_forcemandatorylock:
1137 ctx->mand_lock = 1;
1138 break;
1139 case Opt_setuids:
1140 ctx->setuids = result.negated;
1141 break;
1142 case Opt_intr:
1143 ctx->intr = !result.negated;
1144 break;
1145 case Opt_setuidfromacl:
1146 ctx->setuidfromacl = 1;
1147 break;
1148 case Opt_strictsync:
1149 ctx->nostrictsync = result.negated;
1150 break;
1151 case Opt_serverino:
1152 ctx->server_ino = !result.negated;
1153 break;
1154 case Opt_rwpidforward:
1155 ctx->rwpidforward = 1;
1156 break;
1157 case Opt_modesid:
1158 ctx->mode_ace = 1;
1159 break;
1160 case Opt_cifsacl:
1161 ctx->cifs_acl = !result.negated;
1162 break;
1163 case Opt_acl:
1164 ctx->no_psx_acl = result.negated;
1165 break;
1166 case Opt_locallease:
1167 ctx->local_lease = 1;
1168 break;
1169 case Opt_sign:
1170 ctx->sign = true;
1171 break;
1172 case Opt_ignore_signature:
1173 ctx->sign = true;
1174 ctx->ignore_signature = true;
1175 break;
1176 case Opt_seal:
1177 /* we do not do the following in secFlags because seal
1178 * is a per tree connection (mount) not a per socket
1179 * or per-smb connection option in the protocol
1180 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1181 */
1182 ctx->seal = 1;
1183 break;
1184 case Opt_noac:
1185 pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1186 break;
1187 case Opt_fsc:
1188#ifndef CONFIG_CIFS_FSCACHE
1189 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
1190 goto cifs_parse_mount_err;
1191#endif
1192 ctx->fsc = true;
1193 break;
1194 case Opt_mfsymlinks:
1195 ctx->mfsymlinks = true;
1196 break;
1197 case Opt_multiuser:
1198 ctx->multiuser = true;
1199 break;
1200 case Opt_sloppy:
1201 ctx->sloppy = true;
1202 break;
1203 case Opt_nosharesock:
1204 ctx->nosharesock = true;
1205 break;
1206 case Opt_persistent:
1207 if (result.negated) {
1208 if ((ctx->nopersistent) || (ctx->resilient)) {
1209 cifs_dbg(VFS,
1210 "persistenthandles mount options conflict\n");
1211 goto cifs_parse_mount_err;
1212 }
1213 } else {
1214 ctx->nopersistent = true;
1215 if (ctx->persistent) {
1216 cifs_dbg(VFS,
1217 "persistenthandles mount options conflict\n");
1218 goto cifs_parse_mount_err;
1219 }
1220 }
1221 break;
1222 case Opt_resilient:
1223 if (result.negated) {
1224 ctx->resilient = false; /* already the default */
1225 } else {
1226 ctx->resilient = true;
1227 if (ctx->persistent) {
1228 cifs_dbg(VFS,
1229 "persistenthandles mount options conflict\n");
1230 goto cifs_parse_mount_err;
1231 }
1232 }
1233 break;
1234 case Opt_domainauto:
1235 ctx->domainauto = true;
1236 break;
1237 case Opt_rdma:
1238 ctx->rdma = true;
1239 break;
1240 }
1241
1242 return 0;
1243
1244 cifs_parse_mount_err:
1245 return 1;
1246}
1247
1248int smb3_init_fs_context(struct fs_context *fc)
1249{
1250 struct smb3_fs_context *ctx;
1251 char *nodename = utsname()->nodename;
1252 int i;
1253
1254 ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
1255 if (unlikely(!ctx))
1256 return -ENOMEM;
1257
1258 /*
1259 * does not have to be perfect mapping since field is
1260 * informational, only used for servers that do not support
1261 * port 445 and it can be overridden at mount time
1262 */
1263 memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1264 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
1265 ctx->source_rfc1001_name[i] = toupper(nodename[i]);
1266
1267 ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1268 /*
1269 * null target name indicates to use *SMBSERVR default called name
1270 * if we end up sending RFC1001 session initialize
1271 */
1272 ctx->target_rfc1001_name[0] = 0;
1273 ctx->cred_uid = current_uid();
1274 ctx->linux_uid = current_uid();
1275 ctx->linux_gid = current_gid();
1276 ctx->bsize = 1024 * 1024; /* can improve cp performance significantly */
1277
1278 /*
1279 * default to SFM style remapping of seven reserved characters
1280 * unless user overrides it or we negotiate CIFS POSIX where
1281 * it is unnecessary. Can not simultaneously use more than one mapping
1282 * since then readdir could list files that open could not open
1283 */
1284 ctx->remap = true;
1285
1286 /* default to only allowing write access to owner of the mount */
1287 ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1288
1289 /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1290 /* default is always to request posix paths. */
1291 ctx->posix_paths = 1;
1292 /* default to using server inode numbers where available */
1293 ctx->server_ino = 1;
1294
1295 /* default is to use strict cifs caching semantics */
1296 ctx->strict_io = true;
1297
1298 ctx->actimeo = CIFS_DEF_ACTIMEO;
1299
1300 /* Most clients set timeout to 0, allows server to use its default */
1301 ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1302
1303 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1304 ctx->ops = &smb30_operations;
1305 ctx->vals = &smbdefault_values;
1306
1307 ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1308
1309 /* default to no multichannel (single server connection) */
1310 ctx->multichannel = false;
1311 ctx->max_channels = 1;
1312
1313 ctx->backupuid_specified = false; /* no backup intent for a user */
1314 ctx->backupgid_specified = false; /* no backup intent for a group */
1315
1316/*
1317 * short int override_uid = -1;
1318 * short int override_gid = -1;
1319 * char *nodename = strdup(utsname()->nodename);
1320 * struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
1321 */
1322
1323 fc->fs_private = ctx;
1324 fc->ops = &smb3_fs_context_ops;
1325 return 0;
1326}
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001327
1328void
1329smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
1330{
1331 if (ctx == NULL)
1332 return;
1333
1334 /*
1335 * Make sure this stays in sync with smb3_fs_context_dup()
1336 */
1337 kfree(ctx->mount_options);
1338 ctx->mount_options = NULL;
1339 kfree(ctx->username);
1340 ctx->username = NULL;
1341 kfree_sensitive(ctx->password);
1342 ctx->password = NULL;
1343 kfree(ctx->UNC);
1344 ctx->UNC = NULL;
1345 kfree(ctx->domainname);
1346 ctx->domainname = NULL;
1347 kfree(ctx->nodename);
1348 ctx->nodename = NULL;
1349 kfree(ctx->iocharset);
1350 ctx->iocharset = NULL;
1351 kfree(ctx->prepath);
1352 ctx->prepath = NULL;
1353
1354 unload_nls(ctx->local_nls);
1355 ctx->local_nls = NULL;
1356}
1357
1358void
1359smb3_cleanup_fs_context(struct smb3_fs_context *ctx)
1360{
1361 if (!ctx)
1362 return;
1363 smb3_cleanup_fs_context_contents(ctx);
1364 kfree(ctx);
1365}