blob: 58da674c0365077acc7d174a6d678fb5193d20b5 [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->nodename = NULL;
308 new_ctx->username = NULL;
309 new_ctx->password = NULL;
310 new_ctx->domainname = NULL;
311 new_ctx->UNC = NULL;
312 new_ctx->iocharset = NULL;
313
314 /*
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000315 * Make sure to stay in sync with smb3_cleanup_fs_context_contents()
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000316 */
317 DUP_CTX_STR(prepath);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600318 DUP_CTX_STR(mount_options);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000319 DUP_CTX_STR(username);
320 DUP_CTX_STR(password);
321 DUP_CTX_STR(UNC);
322 DUP_CTX_STR(domainname);
323 DUP_CTX_STR(nodename);
324 DUP_CTX_STR(iocharset);
325
326 return rc;
327}
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000328
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600329static int
330cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3)
331{
332 substring_t args[MAX_OPT_ARGS];
333
334 switch (match_token(value, cifs_smb_version_tokens, args)) {
335#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
336 case Smb_1:
337 if (disable_legacy_dialects) {
338 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
339 return 1;
340 }
341 if (is_smb3) {
342 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
343 return 1;
344 }
345 cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
346 ctx->ops = &smb1_operations;
347 ctx->vals = &smb1_values;
348 break;
349 case Smb_20:
350 if (disable_legacy_dialects) {
351 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
352 return 1;
353 }
354 if (is_smb3) {
355 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
356 return 1;
357 }
358 ctx->ops = &smb20_operations;
359 ctx->vals = &smb20_values;
360 break;
361#else
362 case Smb_1:
363 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
364 return 1;
365 case Smb_20:
366 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
367 return 1;
368#endif /* CIFS_ALLOW_INSECURE_LEGACY */
369 case Smb_21:
370 ctx->ops = &smb21_operations;
371 ctx->vals = &smb21_values;
372 break;
373 case Smb_30:
374 ctx->ops = &smb30_operations;
375 ctx->vals = &smb30_values;
376 break;
377 case Smb_302:
378 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
379 ctx->vals = &smb302_values;
380 break;
381 case Smb_311:
382 ctx->ops = &smb311_operations;
383 ctx->vals = &smb311_values;
384 break;
385 case Smb_3any:
386 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
387 ctx->vals = &smb3any_values;
388 break;
389 case Smb_default:
390 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
391 ctx->vals = &smbdefault_values;
392 break;
393 default:
394 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
395 return 1;
396 }
397 return 0;
398}
399
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000400/*
401 * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath
402 * fields with the result. Returns 0 on success and an error otherwise
403 * (e.g. ENOMEM or EINVAL)
404 */
405int
406smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
407{
408 char *pos;
409 const char *delims = "/\\";
410 size_t len;
411
412 if (unlikely(!devname || !*devname)) {
413 cifs_dbg(VFS, "Device name not specified\n");
414 return -EINVAL;
415 }
416
417 /* make sure we have a valid UNC double delimiter prefix */
418 len = strspn(devname, delims);
419 if (len != 2)
420 return -EINVAL;
421
422 /* find delimiter between host and sharename */
423 pos = strpbrk(devname + 2, delims);
424 if (!pos)
425 return -EINVAL;
426
427 /* skip past delimiter */
428 ++pos;
429
430 /* now go until next delimiter or end of string */
431 len = strcspn(pos, delims);
432
433 /* move "pos" up to delimiter or NULL */
434 pos += len;
435 ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
436 if (!ctx->UNC)
437 return -ENOMEM;
438
439 convert_delimiter(ctx->UNC, '\\');
440
441 /* skip any delimiter */
442 if (*pos == '/' || *pos == '\\')
443 pos++;
444
445 /* If pos is NULL then no prepath */
446 if (!*pos)
447 return 0;
448
449 ctx->prepath = kstrdup(pos, GFP_KERNEL);
450 if (!ctx->prepath)
451 return -ENOMEM;
452
453 return 0;
454}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600455
456static void smb3_fs_context_free(struct fs_context *fc);
457static int smb3_fs_context_parse_param(struct fs_context *fc,
458 struct fs_parameter *param);
459static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
460 void *data);
461static int smb3_get_tree(struct fs_context *fc);
462static int smb3_reconfigure(struct fs_context *fc);
463
464static const struct fs_context_operations smb3_fs_context_ops = {
465 .free = smb3_fs_context_free,
466 .parse_param = smb3_fs_context_parse_param,
467 .parse_monolithic = smb3_fs_context_parse_monolithic,
468 .get_tree = smb3_get_tree,
469 .reconfigure = smb3_reconfigure,
470};
471
472/*
473 * Parse a monolithic block of data from sys_mount().
474 * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data
475 * @ctx: The superblock configuration to fill in.
476 * @data: The data to parse
477 *
478 * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be
479 * called from the ->monolithic_mount_data() fs_context operation.
480 *
481 * Returns 0 on success or the error returned by the ->parse_option() fs_context
482 * operation on failure.
483 */
484static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
485 void *data)
486{
487 struct smb3_fs_context *ctx = smb3_fc2context(fc);
488 char *options = data, *key;
489 int ret = 0;
490
491 if (!options)
492 return 0;
493
494 ctx->mount_options = kstrdup(data, GFP_KERNEL);
495 if (ctx->mount_options == NULL)
496 return -ENOMEM;
497
498 ret = security_sb_eat_lsm_opts(options, &fc->security);
499 if (ret)
500 return ret;
501
502 /* BB Need to add support for sep= here TBD */
503 while ((key = strsep(&options, ",")) != NULL) {
504 if (*key) {
505 size_t v_len = 0;
506 char *value = strchr(key, '=');
507
508 if (value) {
509 if (value == key)
510 continue;
511 *value++ = 0;
512 v_len = strlen(value);
513 }
514 ret = vfs_parse_fs_string(fc, key, value, v_len);
515 if (ret < 0)
516 break;
517 }
518 }
519
520 return ret;
521}
522
523/*
524 * Validate the preparsed information in the config.
525 */
526static int smb3_fs_context_validate(struct fs_context *fc)
527{
528 struct smb3_fs_context *ctx = smb3_fc2context(fc);
529
530 if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
531 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
532 return -1;
533 }
534
535#ifndef CONFIG_KEYS
536 /* Muliuser mounts require CONFIG_KEYS support */
537 if (ctx->multiuser) {
538 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
539 return -1;
540 }
541#endif
542
543 if (ctx->got_version == false)
544 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");
545
546
547 if (!ctx->UNC) {
548 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
549 return -1;
550 }
551
552 /* make sure UNC has a share name */
553 if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
554 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
555 return -1;
556 }
557
558 if (!ctx->got_ip) {
559 int len;
560 const char *slash;
561
562 /* No ip= option specified? Try to get it from UNC */
563 /* Use the address part of the UNC. */
564 slash = strchr(&ctx->UNC[2], '\\');
565 len = slash - &ctx->UNC[2];
566 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
567 &ctx->UNC[2], len)) {
568 pr_err("Unable to determine destination address\n");
569 return -1;
570 }
571 }
572
573 /* set the port that we got earlier */
574 cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
575
576 if (ctx->override_uid && !ctx->uid_specified) {
577 ctx->override_uid = 0;
578 pr_notice("ignoring forceuid mount option specified with no uid= option\n");
579 }
580
581 if (ctx->override_gid && !ctx->gid_specified) {
582 ctx->override_gid = 0;
583 pr_notice("ignoring forcegid mount option specified with no gid= option\n");
584 }
585
586 return 0;
587}
588
589static int smb3_get_tree_common(struct fs_context *fc)
590{
591 struct smb3_fs_context *ctx = smb3_fc2context(fc);
592 struct dentry *root;
593 int rc = 0;
594
595 root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);
596 if (IS_ERR(root))
597 return PTR_ERR(root);
598
599 fc->root = root;
600
601 return rc;
602}
603
604/*
605 * Create an SMB3 superblock from the parameters passed.
606 */
607static int smb3_get_tree(struct fs_context *fc)
608{
609 int err = smb3_fs_context_validate(fc);
610
611 if (err)
612 return err;
613 return smb3_get_tree_common(fc);
614}
615
616static void smb3_fs_context_free(struct fs_context *fc)
617{
618 struct smb3_fs_context *ctx = smb3_fc2context(fc);
619
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000620 smb3_cleanup_fs_context(ctx);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600621}
622
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000623/*
624 * Compare the old and new proposed context during reconfigure
625 * and check if the changes are compatible.
626 */
627static int smb3_verify_reconfigure_ctx(struct smb3_fs_context *new_ctx,
628 struct smb3_fs_context *old_ctx)
629{
Ronnie Sahlberg531f03b2020-12-14 16:40:23 +1000630 if (new_ctx->posix_paths != old_ctx->posix_paths) {
631 cifs_dbg(VFS, "can not change posixpaths during remount\n");
632 return -EINVAL;
633 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000634 if (new_ctx->sectype != old_ctx->sectype) {
635 cifs_dbg(VFS, "can not change sec during remount\n");
636 return -EINVAL;
637 }
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000638 if (new_ctx->multiuser != old_ctx->multiuser) {
639 cifs_dbg(VFS, "can not change multiuser during remount\n");
640 return -EINVAL;
641 }
642 if (new_ctx->UNC &&
643 (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {
644 cifs_dbg(VFS, "can not change UNC during remount\n");
645 return -EINVAL;
646 }
647 if (new_ctx->username &&
648 (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {
649 cifs_dbg(VFS, "can not change username during remount\n");
650 return -EINVAL;
651 }
652 if (new_ctx->password &&
653 (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
654 cifs_dbg(VFS, "can not change password during remount\n");
655 return -EINVAL;
656 }
657 if (new_ctx->domainname &&
658 (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
659 cifs_dbg(VFS, "can not change domainname during remount\n");
660 return -EINVAL;
661 }
662 if (new_ctx->nodename &&
663 (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
664 cifs_dbg(VFS, "can not change nodename during remount\n");
665 return -EINVAL;
666 }
667 if (new_ctx->iocharset &&
668 (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {
669 cifs_dbg(VFS, "can not change iocharset during remount\n");
670 return -EINVAL;
671 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000672
673 return 0;
674}
675
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000676#define STEAL_STRING(cifs_sb, ctx, field) \
677do { \
678 kfree(ctx->field); \
679 ctx->field = cifs_sb->ctx->field; \
680 cifs_sb->ctx->field = NULL; \
681} while (0)
682
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600683static int smb3_reconfigure(struct fs_context *fc)
684{
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000685 struct smb3_fs_context *ctx = smb3_fc2context(fc);
686 struct dentry *root = fc->root;
687 struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
688 int rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600689
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000690 rc = smb3_verify_reconfigure_ctx(ctx, cifs_sb->ctx);
691 if (rc)
692 return rc;
693
694 /*
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000695 * We can not change UNC/username/password/domainname/nodename/iocharset
696 * during reconnect so ignore what we have in the new context and
697 * just use what we already have in cifs_sb->ctx.
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000698 */
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000699 STEAL_STRING(cifs_sb, ctx, UNC);
700 STEAL_STRING(cifs_sb, ctx, username);
701 STEAL_STRING(cifs_sb, ctx, password);
702 STEAL_STRING(cifs_sb, ctx, domainname);
703 STEAL_STRING(cifs_sb, ctx, nodename);
704 STEAL_STRING(cifs_sb, ctx, iocharset);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000705
706 smb3_cleanup_fs_context_contents(cifs_sb->ctx);
707 rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
708
709 return rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600710}
711
712static int smb3_fs_context_parse_param(struct fs_context *fc,
713 struct fs_parameter *param)
714{
715 struct fs_parse_result result;
716 struct smb3_fs_context *ctx = smb3_fc2context(fc);
717 int i, opt;
718 bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
719 bool skip_parsing = false;
720
721 cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
722
723 /*
724 * fs_parse can not handle string options with an empty value so
725 * we will need special handling of them.
726 */
727 if (param->type == fs_value_is_string && param->string[0] == 0) {
728 if (!strcmp("pass", param->key) || !strcmp("password", param->key))
729 skip_parsing = true;
730 }
731
732 if (!skip_parsing) {
733 opt = fs_parse(fc, smb3_fs_parameters, param, &result);
734 if (opt < 0)
735 return ctx->sloppy ? 1 : opt;
736 }
737
738 switch (opt) {
739 case Opt_compress:
740 ctx->compression = UNKNOWN_TYPE;
741 cifs_dbg(VFS,
742 "SMB3 compression support is experimental\n");
743 break;
744 case Opt_nodfs:
745 ctx->nodfs = 1;
746 break;
747 case Opt_hard:
748 if (result.negated)
749 ctx->retry = 0;
750 else
751 ctx->retry = 1;
752 break;
753 case Opt_soft:
754 if (result.negated)
755 ctx->retry = 1;
756 else
757 ctx->retry = 0;
758 break;
759 case Opt_mapposix:
760 if (result.negated)
761 ctx->remap = false;
762 else {
763 ctx->remap = true;
764 ctx->sfu_remap = false; /* disable SFU mapping */
765 }
766 break;
767 case Opt_user_xattr:
768 if (result.negated)
769 ctx->no_xattr = 1;
770 else
771 ctx->no_xattr = 0;
772 break;
773 case Opt_forceuid:
774 if (result.negated)
775 ctx->override_uid = 0;
776 else
777 ctx->override_uid = 1;
778 break;
779 case Opt_forcegid:
780 if (result.negated)
781 ctx->override_gid = 0;
782 else
783 ctx->override_gid = 1;
784 break;
785 case Opt_perm:
786 if (result.negated)
787 ctx->noperm = 1;
788 else
789 ctx->noperm = 0;
790 break;
791 case Opt_dynperm:
792 if (result.negated)
793 ctx->dynperm = 0;
794 else
795 ctx->dynperm = 1;
796 break;
797 case Opt_sfu:
798 if (result.negated)
799 ctx->sfu_emul = 0;
800 else
801 ctx->sfu_emul = 1;
802 break;
803 case Opt_noblocksend:
804 ctx->noblocksnd = 1;
805 break;
806 case Opt_noautotune:
807 ctx->noautotune = 1;
808 break;
809 case Opt_nolease:
810 ctx->no_lease = 1;
811 break;
812 case Opt_nodelete:
813 ctx->nodelete = 1;
814 break;
815 case Opt_multichannel:
816 if (result.negated) {
817 ctx->multichannel = false;
818 ctx->max_channels = 1;
819 } else {
820 ctx->multichannel = true;
821 /* if number of channels not specified, default to 2 */
822 if (ctx->max_channels < 2)
823 ctx->max_channels = 2;
824 }
825 break;
826 case Opt_uid:
827 ctx->linux_uid.val = result.uint_32;
828 ctx->uid_specified = true;
829 break;
830 case Opt_cruid:
831 ctx->cred_uid.val = result.uint_32;
832 break;
833 case Opt_backupgid:
834 ctx->backupgid.val = result.uint_32;
835 ctx->backupgid_specified = true;
836 break;
837 case Opt_gid:
838 ctx->linux_gid.val = result.uint_32;
839 ctx->gid_specified = true;
840 break;
841 case Opt_port:
842 ctx->port = result.uint_32;
843 break;
844 case Opt_file_mode:
845 ctx->file_mode = result.uint_32;
846 break;
847 case Opt_dirmode:
848 ctx->dir_mode = result.uint_32;
849 break;
850 case Opt_min_enc_offload:
851 ctx->min_offload = result.uint_32;
852 break;
853 case Opt_blocksize:
854 /*
855 * inode blocksize realistically should never need to be
856 * less than 16K or greater than 16M and default is 1MB.
857 * Note that small inode block sizes (e.g. 64K) can lead
858 * to very poor performance of common tools like cp and scp
859 */
860 if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||
861 (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {
862 cifs_dbg(VFS, "%s: Invalid blocksize\n",
863 __func__);
864 goto cifs_parse_mount_err;
865 }
866 ctx->bsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000867 ctx->got_bsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600868 break;
869 case Opt_rsize:
870 ctx->rsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000871 ctx->got_rsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600872 break;
873 case Opt_wsize:
874 ctx->wsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000875 ctx->got_wsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600876 break;
877 case Opt_actimeo:
878 ctx->actimeo = HZ * result.uint_32;
879 if (ctx->actimeo > CIFS_MAX_ACTIMEO) {
880 cifs_dbg(VFS, "attribute cache timeout too large\n");
881 goto cifs_parse_mount_err;
882 }
883 break;
884 case Opt_echo_interval:
885 ctx->echo_interval = result.uint_32;
886 break;
887 case Opt_snapshot:
888 ctx->snapshot_time = result.uint_32;
889 break;
890 case Opt_max_credits:
891 if (result.uint_32 < 20 || result.uint_32 > 60000) {
892 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
893 __func__);
894 goto cifs_parse_mount_err;
895 }
896 ctx->max_credits = result.uint_32;
897 break;
898 case Opt_max_channels:
899 if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {
900 cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
901 __func__, CIFS_MAX_CHANNELS);
902 goto cifs_parse_mount_err;
903 }
904 ctx->max_channels = result.uint_32;
905 break;
906 case Opt_handletimeout:
907 ctx->handle_timeout = result.uint_32;
908 if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
909 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
910 goto cifs_parse_mount_err;
911 }
912 break;
913 case Opt_source:
914 kfree(ctx->UNC);
915 ctx->UNC = NULL;
916 switch (smb3_parse_devname(param->string, ctx)) {
917 case 0:
918 break;
919 case -ENOMEM:
920 cifs_dbg(VFS, "Unable to allocate memory for devname\n");
921 goto cifs_parse_mount_err;
922 case -EINVAL:
923 cifs_dbg(VFS, "Malformed UNC in devname\n");
924 goto cifs_parse_mount_err;
925 default:
926 cifs_dbg(VFS, "Unknown error parsing devname\n");
927 goto cifs_parse_mount_err;
928 }
929 fc->source = kstrdup(param->string, GFP_KERNEL);
930 if (fc->source == NULL) {
931 cifs_dbg(VFS, "OOM when copying UNC string\n");
932 goto cifs_parse_mount_err;
933 }
934 break;
935 case Opt_user:
936 kfree(ctx->username);
937 ctx->username = NULL;
938 if (strlen(param->string) == 0) {
939 /* null user, ie. anonymous authentication */
940 ctx->nullauth = 1;
941 break;
942 }
943
944 if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) >
945 CIFS_MAX_USERNAME_LEN) {
946 pr_warn("username too long\n");
947 goto cifs_parse_mount_err;
948 }
949 ctx->username = kstrdup(param->string, GFP_KERNEL);
950 if (ctx->username == NULL) {
951 cifs_dbg(VFS, "OOM when copying username string\n");
952 goto cifs_parse_mount_err;
953 }
954 break;
955 case Opt_pass:
956 kfree(ctx->password);
957 ctx->password = NULL;
958 if (strlen(param->string) == 0)
959 break;
960
961 ctx->password = kstrdup(param->string, GFP_KERNEL);
962 if (ctx->password == NULL) {
963 cifs_dbg(VFS, "OOM when copying password string\n");
964 goto cifs_parse_mount_err;
965 }
966 break;
967 case Opt_ip:
968 if (strlen(param->string) == 0) {
969 ctx->got_ip = false;
970 break;
971 }
972 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
973 param->string,
974 strlen(param->string))) {
975 pr_err("bad ip= option (%s)\n", param->string);
976 goto cifs_parse_mount_err;
977 }
978 ctx->got_ip = true;
979 break;
980 case Opt_domain:
981 if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN)
982 == CIFS_MAX_DOMAINNAME_LEN) {
983 pr_warn("domain name too long\n");
984 goto cifs_parse_mount_err;
985 }
986
987 kfree(ctx->domainname);
988 ctx->domainname = kstrdup(param->string, GFP_KERNEL);
989 if (ctx->domainname == NULL) {
990 cifs_dbg(VFS, "OOM when copying domainname string\n");
991 goto cifs_parse_mount_err;
992 }
993 cifs_dbg(FYI, "Domain name set\n");
994 break;
995 case Opt_srcaddr:
996 if (!cifs_convert_address(
997 (struct sockaddr *)&ctx->srcaddr,
998 param->string, strlen(param->string))) {
999 pr_warn("Could not parse srcaddr: %s\n",
1000 param->string);
1001 goto cifs_parse_mount_err;
1002 }
1003 break;
1004 case Opt_iocharset:
1005 if (strnlen(param->string, 1024) >= 65) {
1006 pr_warn("iocharset name too long\n");
1007 goto cifs_parse_mount_err;
1008 }
1009
1010 if (strncasecmp(param->string, "default", 7) != 0) {
1011 kfree(ctx->iocharset);
1012 ctx->iocharset = kstrdup(param->string, GFP_KERNEL);
1013 if (ctx->iocharset == NULL) {
1014 cifs_dbg(VFS, "OOM when copying iocharset string\n");
1015 goto cifs_parse_mount_err;
1016 }
1017 }
1018 /* if iocharset not set then load_nls_default
1019 * is used by caller
1020 */
1021 cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
1022 break;
1023 case Opt_netbiosname:
1024 memset(ctx->source_rfc1001_name, 0x20,
1025 RFC1001_NAME_LEN);
1026 /*
1027 * FIXME: are there cases in which a comma can
1028 * be valid in workstation netbios name (and
1029 * need special handling)?
1030 */
1031 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1032 /* don't ucase netbiosname for user */
1033 if (param->string[i] == 0)
1034 break;
1035 ctx->source_rfc1001_name[i] = param->string[i];
1036 }
1037 /* The string has 16th byte zero still from
1038 * set at top of the function
1039 */
1040 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1041 pr_warn("netbiosname longer than 15 truncated\n");
1042 break;
1043 case Opt_servern:
1044 /* last byte, type, is 0x20 for servr type */
1045 memset(ctx->target_rfc1001_name, 0x20,
1046 RFC1001_NAME_LEN_WITH_NULL);
1047 /*
1048 * BB are there cases in which a comma can be valid in this
1049 * workstation netbios name (and need special handling)?
1050 */
1051
1052 /* user or mount helper must uppercase the netbios name */
1053 for (i = 0; i < 15; i++) {
1054 if (param->string[i] == 0)
1055 break;
1056 ctx->target_rfc1001_name[i] = param->string[i];
1057 }
1058
1059 /* The string has 16th byte zero still from set at top of function */
1060 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1061 pr_warn("server netbiosname longer than 15 truncated\n");
1062 break;
1063 case Opt_ver:
1064 /* version of mount userspace tools, not dialect */
1065 /* If interface changes in mount.cifs bump to new ver */
1066 if (strncasecmp(param->string, "1", 1) == 0) {
1067 if (strlen(param->string) > 1) {
1068 pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
1069 param->string);
1070 goto cifs_parse_mount_err;
1071 }
1072 /* This is the default */
1073 break;
1074 }
1075 /* For all other value, error */
1076 pr_warn("Invalid mount helper version specified\n");
1077 goto cifs_parse_mount_err;
1078 case Opt_vers:
1079 /* protocol version (dialect) */
1080 if (cifs_parse_smb_version(param->string, ctx, is_smb3) != 0)
1081 goto cifs_parse_mount_err;
1082 ctx->got_version = true;
1083 break;
1084 case Opt_sec:
1085 if (cifs_parse_security_flavors(param->string, ctx) != 0)
1086 goto cifs_parse_mount_err;
1087 break;
1088 case Opt_cache:
1089 if (cifs_parse_cache_flavor(param->string, ctx) != 0)
1090 goto cifs_parse_mount_err;
1091 break;
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001092 case Opt_witness:
1093#ifndef CONFIG_CIFS_SWN_UPCALL
1094 cifs_dbg(VFS, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
1095 goto cifs_parse_mount_err;
1096#endif
1097 ctx->witness = true;
1098 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001099 case Opt_rootfs:
1100#ifdef CONFIG_CIFS_ROOT
1101 ctx->rootfs = true;
1102#endif
1103 break;
1104 case Opt_posixpaths:
1105 if (result.negated)
1106 ctx->posix_paths = 0;
1107 else
1108 ctx->posix_paths = 1;
1109 break;
1110 case Opt_unix:
1111 if (result.negated)
1112 ctx->linux_ext = 0;
1113 else
1114 ctx->no_linux_ext = 1;
1115 break;
1116 case Opt_nocase:
1117 ctx->nocase = 1;
1118 break;
1119 case Opt_brl:
1120 if (result.negated) {
1121 /*
1122 * turn off mandatory locking in mode
1123 * if remote locking is turned off since the
1124 * local vfs will do advisory
1125 */
1126 if (ctx->file_mode ==
1127 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1128 ctx->file_mode = S_IALLUGO;
1129 ctx->nobrl = 1;
1130 } else
1131 ctx->nobrl = 0;
1132 break;
1133 case Opt_handlecache:
1134 if (result.negated)
1135 ctx->nohandlecache = 1;
1136 else
1137 ctx->nohandlecache = 0;
1138 break;
1139 case Opt_forcemandatorylock:
1140 ctx->mand_lock = 1;
1141 break;
1142 case Opt_setuids:
1143 ctx->setuids = result.negated;
1144 break;
1145 case Opt_intr:
1146 ctx->intr = !result.negated;
1147 break;
1148 case Opt_setuidfromacl:
1149 ctx->setuidfromacl = 1;
1150 break;
1151 case Opt_strictsync:
1152 ctx->nostrictsync = result.negated;
1153 break;
1154 case Opt_serverino:
1155 ctx->server_ino = !result.negated;
1156 break;
1157 case Opt_rwpidforward:
1158 ctx->rwpidforward = 1;
1159 break;
1160 case Opt_modesid:
1161 ctx->mode_ace = 1;
1162 break;
1163 case Opt_cifsacl:
1164 ctx->cifs_acl = !result.negated;
1165 break;
1166 case Opt_acl:
1167 ctx->no_psx_acl = result.negated;
1168 break;
1169 case Opt_locallease:
1170 ctx->local_lease = 1;
1171 break;
1172 case Opt_sign:
1173 ctx->sign = true;
1174 break;
1175 case Opt_ignore_signature:
1176 ctx->sign = true;
1177 ctx->ignore_signature = true;
1178 break;
1179 case Opt_seal:
1180 /* we do not do the following in secFlags because seal
1181 * is a per tree connection (mount) not a per socket
1182 * or per-smb connection option in the protocol
1183 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1184 */
1185 ctx->seal = 1;
1186 break;
1187 case Opt_noac:
1188 pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1189 break;
1190 case Opt_fsc:
1191#ifndef CONFIG_CIFS_FSCACHE
1192 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
1193 goto cifs_parse_mount_err;
1194#endif
1195 ctx->fsc = true;
1196 break;
1197 case Opt_mfsymlinks:
1198 ctx->mfsymlinks = true;
1199 break;
1200 case Opt_multiuser:
1201 ctx->multiuser = true;
1202 break;
1203 case Opt_sloppy:
1204 ctx->sloppy = true;
1205 break;
1206 case Opt_nosharesock:
1207 ctx->nosharesock = true;
1208 break;
1209 case Opt_persistent:
1210 if (result.negated) {
1211 if ((ctx->nopersistent) || (ctx->resilient)) {
1212 cifs_dbg(VFS,
1213 "persistenthandles mount options conflict\n");
1214 goto cifs_parse_mount_err;
1215 }
1216 } else {
1217 ctx->nopersistent = true;
1218 if (ctx->persistent) {
1219 cifs_dbg(VFS,
1220 "persistenthandles mount options conflict\n");
1221 goto cifs_parse_mount_err;
1222 }
1223 }
1224 break;
1225 case Opt_resilient:
1226 if (result.negated) {
1227 ctx->resilient = false; /* already the default */
1228 } else {
1229 ctx->resilient = true;
1230 if (ctx->persistent) {
1231 cifs_dbg(VFS,
1232 "persistenthandles mount options conflict\n");
1233 goto cifs_parse_mount_err;
1234 }
1235 }
1236 break;
1237 case Opt_domainauto:
1238 ctx->domainauto = true;
1239 break;
1240 case Opt_rdma:
1241 ctx->rdma = true;
1242 break;
1243 }
1244
1245 return 0;
1246
1247 cifs_parse_mount_err:
1248 return 1;
1249}
1250
1251int smb3_init_fs_context(struct fs_context *fc)
1252{
1253 struct smb3_fs_context *ctx;
1254 char *nodename = utsname()->nodename;
1255 int i;
1256
1257 ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
1258 if (unlikely(!ctx))
1259 return -ENOMEM;
1260
1261 /*
1262 * does not have to be perfect mapping since field is
1263 * informational, only used for servers that do not support
1264 * port 445 and it can be overridden at mount time
1265 */
1266 memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1267 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
1268 ctx->source_rfc1001_name[i] = toupper(nodename[i]);
1269
1270 ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1271 /*
1272 * null target name indicates to use *SMBSERVR default called name
1273 * if we end up sending RFC1001 session initialize
1274 */
1275 ctx->target_rfc1001_name[0] = 0;
1276 ctx->cred_uid = current_uid();
1277 ctx->linux_uid = current_uid();
1278 ctx->linux_gid = current_gid();
1279 ctx->bsize = 1024 * 1024; /* can improve cp performance significantly */
1280
1281 /*
1282 * default to SFM style remapping of seven reserved characters
1283 * unless user overrides it or we negotiate CIFS POSIX where
1284 * it is unnecessary. Can not simultaneously use more than one mapping
1285 * since then readdir could list files that open could not open
1286 */
1287 ctx->remap = true;
1288
1289 /* default to only allowing write access to owner of the mount */
1290 ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1291
1292 /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1293 /* default is always to request posix paths. */
1294 ctx->posix_paths = 1;
1295 /* default to using server inode numbers where available */
1296 ctx->server_ino = 1;
1297
1298 /* default is to use strict cifs caching semantics */
1299 ctx->strict_io = true;
1300
1301 ctx->actimeo = CIFS_DEF_ACTIMEO;
1302
1303 /* Most clients set timeout to 0, allows server to use its default */
1304 ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1305
1306 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1307 ctx->ops = &smb30_operations;
1308 ctx->vals = &smbdefault_values;
1309
1310 ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1311
1312 /* default to no multichannel (single server connection) */
1313 ctx->multichannel = false;
1314 ctx->max_channels = 1;
1315
1316 ctx->backupuid_specified = false; /* no backup intent for a user */
1317 ctx->backupgid_specified = false; /* no backup intent for a group */
1318
1319/*
1320 * short int override_uid = -1;
1321 * short int override_gid = -1;
1322 * char *nodename = strdup(utsname()->nodename);
1323 * struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
1324 */
1325
1326 fc->fs_private = ctx;
1327 fc->ops = &smb3_fs_context_ops;
1328 return 0;
1329}
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001330
1331void
1332smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
1333{
1334 if (ctx == NULL)
1335 return;
1336
1337 /*
1338 * Make sure this stays in sync with smb3_fs_context_dup()
1339 */
1340 kfree(ctx->mount_options);
1341 ctx->mount_options = NULL;
1342 kfree(ctx->username);
1343 ctx->username = NULL;
1344 kfree_sensitive(ctx->password);
1345 ctx->password = NULL;
1346 kfree(ctx->UNC);
1347 ctx->UNC = NULL;
1348 kfree(ctx->domainname);
1349 ctx->domainname = NULL;
1350 kfree(ctx->nodename);
1351 ctx->nodename = NULL;
1352 kfree(ctx->iocharset);
1353 ctx->iocharset = NULL;
1354 kfree(ctx->prepath);
1355 ctx->prepath = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001356}
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}