blob: 29b99e68ec80b531655f71b1443332999ecb26bc [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),
Steve French27cf9482020-12-16 01:22:54 -060097 fsparam_flag("idsfromsid", Opt_setuidfromacl),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -060098 fsparam_flag_no("setuids", Opt_setuids),
99 fsparam_flag_no("dynperm", Opt_dynperm),
100 fsparam_flag_no("intr", Opt_intr),
101 fsparam_flag_no("strictsync", Opt_strictsync),
102 fsparam_flag_no("serverino", Opt_serverino),
103 fsparam_flag("rwpidforward", Opt_rwpidforward),
104 fsparam_flag("cifsacl", Opt_cifsacl),
105 fsparam_flag_no("acl", Opt_acl),
106 fsparam_flag("locallease", Opt_locallease),
107 fsparam_flag("sign", Opt_sign),
108 fsparam_flag("ignore_signature", Opt_ignore_signature),
Steve French27cf9482020-12-16 01:22:54 -0600109 fsparam_flag("signloosely", Opt_ignore_signature),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600110 fsparam_flag("seal", Opt_seal),
111 fsparam_flag("noac", Opt_noac),
112 fsparam_flag("fsc", Opt_fsc),
113 fsparam_flag("mfsymlinks", Opt_mfsymlinks),
114 fsparam_flag("multiuser", Opt_multiuser),
115 fsparam_flag("sloppy", Opt_sloppy),
116 fsparam_flag("nosharesock", Opt_nosharesock),
Steve French27cf9482020-12-16 01:22:54 -0600117 fsparam_flag_no("persistenthandles", Opt_persistent),
118 fsparam_flag_no("resilienthandles", Opt_resilient),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600119 fsparam_flag("domainauto", Opt_domainauto),
120 fsparam_flag("rdma", Opt_rdma),
121 fsparam_flag("modesid", Opt_modesid),
Steve French27cf9482020-12-16 01:22:54 -0600122 fsparam_flag("modefromsid", Opt_modesid),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600123 fsparam_flag("rootfs", Opt_rootfs),
124 fsparam_flag("compress", Opt_compress),
Samuel Cabrero0ac4e292020-12-11 22:59:29 -0600125 fsparam_flag("witness", Opt_witness),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600126
127 /* Mount options which take numeric value */
128 fsparam_u32("backupuid", Opt_backupuid),
129 fsparam_u32("backupgid", Opt_backupgid),
130 fsparam_u32("uid", Opt_uid),
131 fsparam_u32("cruid", Opt_cruid),
132 fsparam_u32("gid", Opt_gid),
133 fsparam_u32("file_mode", Opt_file_mode),
134 fsparam_u32("dirmode", Opt_dirmode),
135 fsparam_u32("dir_mode", Opt_dirmode),
136 fsparam_u32("port", Opt_port),
137 fsparam_u32("min_enc_offload", Opt_min_enc_offload),
Steve French27cf9482020-12-16 01:22:54 -0600138 fsparam_u32("esize", Opt_min_enc_offload),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600139 fsparam_u32("bsize", Opt_blocksize),
140 fsparam_u32("rsize", Opt_rsize),
141 fsparam_u32("wsize", Opt_wsize),
142 fsparam_u32("actimeo", Opt_actimeo),
143 fsparam_u32("echo_interval", Opt_echo_interval),
144 fsparam_u32("max_credits", Opt_max_credits),
145 fsparam_u32("handletimeout", Opt_handletimeout),
146 fsparam_u32("snapshot", Opt_snapshot),
147 fsparam_u32("max_channels", Opt_max_channels),
148
149 /* Mount options which take string value */
150 fsparam_string("source", Opt_source),
151 fsparam_string("unc", Opt_source),
152 fsparam_string("user", Opt_user),
153 fsparam_string("username", Opt_user),
154 fsparam_string("pass", Opt_pass),
155 fsparam_string("password", Opt_pass),
156 fsparam_string("ip", Opt_ip),
157 fsparam_string("addr", Opt_ip),
158 fsparam_string("domain", Opt_domain),
159 fsparam_string("dom", Opt_domain),
160 fsparam_string("srcaddr", Opt_srcaddr),
161 fsparam_string("iocharset", Opt_iocharset),
162 fsparam_string("netbiosname", Opt_netbiosname),
163 fsparam_string("servern", Opt_servern),
164 fsparam_string("ver", Opt_ver),
165 fsparam_string("vers", Opt_vers),
166 fsparam_string("sec", Opt_sec),
167 fsparam_string("cache", Opt_cache),
168
169 /* Arguments that should be ignored */
170 fsparam_flag("guest", Opt_ignore),
171 fsparam_flag("noatime", Opt_ignore),
172 fsparam_flag("relatime", Opt_ignore),
173 fsparam_flag("_netdev", Opt_ignore),
174 fsparam_flag_no("suid", Opt_ignore),
175 fsparam_flag_no("exec", Opt_ignore),
176 fsparam_flag_no("dev", Opt_ignore),
177 fsparam_flag_no("mand", Opt_ignore),
178 fsparam_string("cred", Opt_ignore),
179 fsparam_string("credentials", Opt_ignore),
Dmitry Osipenko427c4f02020-12-14 14:37:45 +0300180 {}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600181};
182
183int
184cifs_parse_security_flavors(char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000185{
186
187 substring_t args[MAX_OPT_ARGS];
188
189 /*
190 * With mount options, the last one should win. Reset any existing
191 * settings back to default.
192 */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600193 ctx->sectype = Unspecified;
194 ctx->sign = false;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000195
196 switch (match_token(value, cifs_secflavor_tokens, args)) {
197 case Opt_sec_krb5p:
198 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
199 return 1;
200 case Opt_sec_krb5i:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600201 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000202 fallthrough;
203 case Opt_sec_krb5:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600204 ctx->sectype = Kerberos;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000205 break;
206 case Opt_sec_ntlmsspi:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600207 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000208 fallthrough;
209 case Opt_sec_ntlmssp:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600210 ctx->sectype = RawNTLMSSP;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000211 break;
212 case Opt_sec_ntlmi:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600213 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000214 fallthrough;
215 case Opt_ntlm:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600216 ctx->sectype = NTLM;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000217 break;
218 case Opt_sec_ntlmv2i:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600219 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000220 fallthrough;
221 case Opt_sec_ntlmv2:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600222 ctx->sectype = NTLMv2;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000223 break;
224#ifdef CONFIG_CIFS_WEAK_PW_HASH
225 case Opt_sec_lanman:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600226 ctx->sectype = LANMAN;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000227 break;
228#endif
229 case Opt_sec_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600230 ctx->nullauth = 1;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000231 break;
232 default:
233 cifs_dbg(VFS, "bad security option: %s\n", value);
234 return 1;
235 }
236
237 return 0;
238}
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000239
240static const match_table_t cifs_cacheflavor_tokens = {
241 { Opt_cache_loose, "loose" },
242 { Opt_cache_strict, "strict" },
243 { Opt_cache_none, "none" },
244 { Opt_cache_ro, "ro" },
245 { Opt_cache_rw, "singleclient" },
246 { Opt_cache_err, NULL }
247};
248
249int
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600250cifs_parse_cache_flavor(char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000251{
252 substring_t args[MAX_OPT_ARGS];
253
254 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
255 case Opt_cache_loose:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600256 ctx->direct_io = false;
257 ctx->strict_io = false;
258 ctx->cache_ro = false;
259 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000260 break;
261 case Opt_cache_strict:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600262 ctx->direct_io = false;
263 ctx->strict_io = true;
264 ctx->cache_ro = false;
265 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000266 break;
267 case Opt_cache_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600268 ctx->direct_io = true;
269 ctx->strict_io = false;
270 ctx->cache_ro = false;
271 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000272 break;
273 case Opt_cache_ro:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600274 ctx->direct_io = false;
275 ctx->strict_io = false;
276 ctx->cache_ro = true;
277 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000278 break;
279 case Opt_cache_rw:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600280 ctx->direct_io = false;
281 ctx->strict_io = false;
282 ctx->cache_ro = false;
283 ctx->cache_rw = true;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000284 break;
285 default:
286 cifs_dbg(VFS, "bad cache= option: %s\n", value);
287 return 1;
288 }
289 return 0;
290}
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000291
292#define DUP_CTX_STR(field) \
293do { \
294 if (ctx->field) { \
295 new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC); \
296 if (new_ctx->field == NULL) { \
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000297 smb3_cleanup_fs_context_contents(new_ctx); \
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000298 return -ENOMEM; \
299 } \
300 } \
301} while (0)
302
303int
304smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)
305{
306 int rc = 0;
307
308 memcpy(new_ctx, ctx, sizeof(*ctx));
309 new_ctx->prepath = NULL;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600310 new_ctx->mount_options = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000311 new_ctx->nodename = NULL;
312 new_ctx->username = NULL;
313 new_ctx->password = NULL;
314 new_ctx->domainname = NULL;
315 new_ctx->UNC = NULL;
316 new_ctx->iocharset = NULL;
317
318 /*
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000319 * Make sure to stay in sync with smb3_cleanup_fs_context_contents()
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000320 */
321 DUP_CTX_STR(prepath);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600322 DUP_CTX_STR(mount_options);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000323 DUP_CTX_STR(username);
324 DUP_CTX_STR(password);
325 DUP_CTX_STR(UNC);
326 DUP_CTX_STR(domainname);
327 DUP_CTX_STR(nodename);
328 DUP_CTX_STR(iocharset);
329
330 return rc;
331}
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000332
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600333static int
334cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3)
335{
336 substring_t args[MAX_OPT_ARGS];
337
338 switch (match_token(value, cifs_smb_version_tokens, args)) {
339#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
340 case Smb_1:
341 if (disable_legacy_dialects) {
342 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
343 return 1;
344 }
345 if (is_smb3) {
346 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
347 return 1;
348 }
349 cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
350 ctx->ops = &smb1_operations;
351 ctx->vals = &smb1_values;
352 break;
353 case Smb_20:
354 if (disable_legacy_dialects) {
355 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
356 return 1;
357 }
358 if (is_smb3) {
359 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
360 return 1;
361 }
362 ctx->ops = &smb20_operations;
363 ctx->vals = &smb20_values;
364 break;
365#else
366 case Smb_1:
367 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
368 return 1;
369 case Smb_20:
370 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
371 return 1;
372#endif /* CIFS_ALLOW_INSECURE_LEGACY */
373 case Smb_21:
374 ctx->ops = &smb21_operations;
375 ctx->vals = &smb21_values;
376 break;
377 case Smb_30:
378 ctx->ops = &smb30_operations;
379 ctx->vals = &smb30_values;
380 break;
381 case Smb_302:
382 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
383 ctx->vals = &smb302_values;
384 break;
385 case Smb_311:
386 ctx->ops = &smb311_operations;
387 ctx->vals = &smb311_values;
388 break;
389 case Smb_3any:
390 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
391 ctx->vals = &smb3any_values;
392 break;
393 case Smb_default:
394 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
395 ctx->vals = &smbdefault_values;
396 break;
397 default:
398 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
399 return 1;
400 }
401 return 0;
402}
403
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000404/*
405 * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath
406 * fields with the result. Returns 0 on success and an error otherwise
407 * (e.g. ENOMEM or EINVAL)
408 */
409int
410smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
411{
412 char *pos;
413 const char *delims = "/\\";
414 size_t len;
415
416 if (unlikely(!devname || !*devname)) {
417 cifs_dbg(VFS, "Device name not specified\n");
418 return -EINVAL;
419 }
420
421 /* make sure we have a valid UNC double delimiter prefix */
422 len = strspn(devname, delims);
423 if (len != 2)
424 return -EINVAL;
425
426 /* find delimiter between host and sharename */
427 pos = strpbrk(devname + 2, delims);
428 if (!pos)
429 return -EINVAL;
430
431 /* skip past delimiter */
432 ++pos;
433
434 /* now go until next delimiter or end of string */
435 len = strcspn(pos, delims);
436
437 /* move "pos" up to delimiter or NULL */
438 pos += len;
439 ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
440 if (!ctx->UNC)
441 return -ENOMEM;
442
443 convert_delimiter(ctx->UNC, '\\');
444
445 /* skip any delimiter */
446 if (*pos == '/' || *pos == '\\')
447 pos++;
448
449 /* If pos is NULL then no prepath */
450 if (!*pos)
451 return 0;
452
453 ctx->prepath = kstrdup(pos, GFP_KERNEL);
454 if (!ctx->prepath)
455 return -ENOMEM;
456
457 return 0;
458}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600459
460static void smb3_fs_context_free(struct fs_context *fc);
461static int smb3_fs_context_parse_param(struct fs_context *fc,
462 struct fs_parameter *param);
463static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
464 void *data);
465static int smb3_get_tree(struct fs_context *fc);
466static int smb3_reconfigure(struct fs_context *fc);
467
468static const struct fs_context_operations smb3_fs_context_ops = {
469 .free = smb3_fs_context_free,
470 .parse_param = smb3_fs_context_parse_param,
471 .parse_monolithic = smb3_fs_context_parse_monolithic,
472 .get_tree = smb3_get_tree,
473 .reconfigure = smb3_reconfigure,
474};
475
476/*
477 * Parse a monolithic block of data from sys_mount().
478 * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data
479 * @ctx: The superblock configuration to fill in.
480 * @data: The data to parse
481 *
482 * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be
483 * called from the ->monolithic_mount_data() fs_context operation.
484 *
485 * Returns 0 on success or the error returned by the ->parse_option() fs_context
486 * operation on failure.
487 */
488static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
489 void *data)
490{
491 struct smb3_fs_context *ctx = smb3_fc2context(fc);
492 char *options = data, *key;
493 int ret = 0;
494
495 if (!options)
496 return 0;
497
498 ctx->mount_options = kstrdup(data, GFP_KERNEL);
499 if (ctx->mount_options == NULL)
500 return -ENOMEM;
501
502 ret = security_sb_eat_lsm_opts(options, &fc->security);
503 if (ret)
504 return ret;
505
506 /* BB Need to add support for sep= here TBD */
507 while ((key = strsep(&options, ",")) != NULL) {
508 if (*key) {
509 size_t v_len = 0;
510 char *value = strchr(key, '=');
511
512 if (value) {
513 if (value == key)
514 continue;
515 *value++ = 0;
516 v_len = strlen(value);
517 }
518 ret = vfs_parse_fs_string(fc, key, value, v_len);
519 if (ret < 0)
520 break;
521 }
522 }
523
524 return ret;
525}
526
527/*
528 * Validate the preparsed information in the config.
529 */
530static int smb3_fs_context_validate(struct fs_context *fc)
531{
532 struct smb3_fs_context *ctx = smb3_fc2context(fc);
533
534 if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
535 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
536 return -1;
537 }
538
539#ifndef CONFIG_KEYS
540 /* Muliuser mounts require CONFIG_KEYS support */
541 if (ctx->multiuser) {
542 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
543 return -1;
544 }
545#endif
546
547 if (ctx->got_version == false)
548 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");
549
550
551 if (!ctx->UNC) {
552 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
553 return -1;
554 }
555
556 /* make sure UNC has a share name */
557 if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
558 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
559 return -1;
560 }
561
562 if (!ctx->got_ip) {
563 int len;
564 const char *slash;
565
566 /* No ip= option specified? Try to get it from UNC */
567 /* Use the address part of the UNC. */
568 slash = strchr(&ctx->UNC[2], '\\');
569 len = slash - &ctx->UNC[2];
570 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
571 &ctx->UNC[2], len)) {
572 pr_err("Unable to determine destination address\n");
573 return -1;
574 }
575 }
576
577 /* set the port that we got earlier */
578 cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
579
580 if (ctx->override_uid && !ctx->uid_specified) {
581 ctx->override_uid = 0;
582 pr_notice("ignoring forceuid mount option specified with no uid= option\n");
583 }
584
585 if (ctx->override_gid && !ctx->gid_specified) {
586 ctx->override_gid = 0;
587 pr_notice("ignoring forcegid mount option specified with no gid= option\n");
588 }
589
590 return 0;
591}
592
593static int smb3_get_tree_common(struct fs_context *fc)
594{
595 struct smb3_fs_context *ctx = smb3_fc2context(fc);
596 struct dentry *root;
597 int rc = 0;
598
599 root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);
600 if (IS_ERR(root))
601 return PTR_ERR(root);
602
603 fc->root = root;
604
605 return rc;
606}
607
608/*
609 * Create an SMB3 superblock from the parameters passed.
610 */
611static int smb3_get_tree(struct fs_context *fc)
612{
613 int err = smb3_fs_context_validate(fc);
614
615 if (err)
616 return err;
617 return smb3_get_tree_common(fc);
618}
619
620static void smb3_fs_context_free(struct fs_context *fc)
621{
622 struct smb3_fs_context *ctx = smb3_fc2context(fc);
623
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000624 smb3_cleanup_fs_context(ctx);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600625}
626
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000627/*
628 * Compare the old and new proposed context during reconfigure
629 * and check if the changes are compatible.
630 */
631static int smb3_verify_reconfigure_ctx(struct smb3_fs_context *new_ctx,
632 struct smb3_fs_context *old_ctx)
633{
Ronnie Sahlberg531f03b2020-12-14 16:40:23 +1000634 if (new_ctx->posix_paths != old_ctx->posix_paths) {
635 cifs_dbg(VFS, "can not change posixpaths during remount\n");
636 return -EINVAL;
637 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000638 if (new_ctx->sectype != old_ctx->sectype) {
639 cifs_dbg(VFS, "can not change sec during remount\n");
640 return -EINVAL;
641 }
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000642 if (new_ctx->multiuser != old_ctx->multiuser) {
643 cifs_dbg(VFS, "can not change multiuser during remount\n");
644 return -EINVAL;
645 }
646 if (new_ctx->UNC &&
647 (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {
648 cifs_dbg(VFS, "can not change UNC during remount\n");
649 return -EINVAL;
650 }
651 if (new_ctx->username &&
652 (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {
653 cifs_dbg(VFS, "can not change username during remount\n");
654 return -EINVAL;
655 }
656 if (new_ctx->password &&
657 (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
658 cifs_dbg(VFS, "can not change password during remount\n");
659 return -EINVAL;
660 }
661 if (new_ctx->domainname &&
662 (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
663 cifs_dbg(VFS, "can not change domainname during remount\n");
664 return -EINVAL;
665 }
666 if (new_ctx->nodename &&
667 (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
668 cifs_dbg(VFS, "can not change nodename during remount\n");
669 return -EINVAL;
670 }
671 if (new_ctx->iocharset &&
672 (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {
673 cifs_dbg(VFS, "can not change iocharset during remount\n");
674 return -EINVAL;
675 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000676
677 return 0;
678}
679
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000680#define STEAL_STRING(cifs_sb, ctx, field) \
681do { \
682 kfree(ctx->field); \
683 ctx->field = cifs_sb->ctx->field; \
684 cifs_sb->ctx->field = NULL; \
685} while (0)
686
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600687static int smb3_reconfigure(struct fs_context *fc)
688{
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000689 struct smb3_fs_context *ctx = smb3_fc2context(fc);
690 struct dentry *root = fc->root;
691 struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
692 int rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600693
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000694 rc = smb3_verify_reconfigure_ctx(ctx, cifs_sb->ctx);
695 if (rc)
696 return rc;
697
698 /*
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000699 * We can not change UNC/username/password/domainname/nodename/iocharset
700 * during reconnect so ignore what we have in the new context and
701 * just use what we already have in cifs_sb->ctx.
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000702 */
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000703 STEAL_STRING(cifs_sb, ctx, UNC);
704 STEAL_STRING(cifs_sb, ctx, username);
705 STEAL_STRING(cifs_sb, ctx, password);
706 STEAL_STRING(cifs_sb, ctx, domainname);
707 STEAL_STRING(cifs_sb, ctx, nodename);
708 STEAL_STRING(cifs_sb, ctx, iocharset);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000709
710 smb3_cleanup_fs_context_contents(cifs_sb->ctx);
711 rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
Ronnie Sahlberg1cb6c3d2020-12-14 16:40:26 +1000712 smb3_update_mnt_flags(cifs_sb);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000713
714 return rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600715}
716
717static int smb3_fs_context_parse_param(struct fs_context *fc,
718 struct fs_parameter *param)
719{
720 struct fs_parse_result result;
721 struct smb3_fs_context *ctx = smb3_fc2context(fc);
722 int i, opt;
723 bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
724 bool skip_parsing = false;
725
726 cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
727
728 /*
729 * fs_parse can not handle string options with an empty value so
730 * we will need special handling of them.
731 */
732 if (param->type == fs_value_is_string && param->string[0] == 0) {
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000733 if (!strcmp("pass", param->key) || !strcmp("password", param->key)) {
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600734 skip_parsing = true;
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000735 opt = Opt_pass;
736 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600737 }
738
739 if (!skip_parsing) {
740 opt = fs_parse(fc, smb3_fs_parameters, param, &result);
741 if (opt < 0)
742 return ctx->sloppy ? 1 : opt;
743 }
744
745 switch (opt) {
746 case Opt_compress:
747 ctx->compression = UNKNOWN_TYPE;
748 cifs_dbg(VFS,
749 "SMB3 compression support is experimental\n");
750 break;
751 case Opt_nodfs:
752 ctx->nodfs = 1;
753 break;
754 case Opt_hard:
755 if (result.negated)
756 ctx->retry = 0;
757 else
758 ctx->retry = 1;
759 break;
760 case Opt_soft:
761 if (result.negated)
762 ctx->retry = 1;
763 else
764 ctx->retry = 0;
765 break;
766 case Opt_mapposix:
767 if (result.negated)
768 ctx->remap = false;
769 else {
770 ctx->remap = true;
771 ctx->sfu_remap = false; /* disable SFU mapping */
772 }
773 break;
774 case Opt_user_xattr:
775 if (result.negated)
776 ctx->no_xattr = 1;
777 else
778 ctx->no_xattr = 0;
779 break;
780 case Opt_forceuid:
781 if (result.negated)
782 ctx->override_uid = 0;
783 else
784 ctx->override_uid = 1;
785 break;
786 case Opt_forcegid:
787 if (result.negated)
788 ctx->override_gid = 0;
789 else
790 ctx->override_gid = 1;
791 break;
792 case Opt_perm:
793 if (result.negated)
794 ctx->noperm = 1;
795 else
796 ctx->noperm = 0;
797 break;
798 case Opt_dynperm:
799 if (result.negated)
800 ctx->dynperm = 0;
801 else
802 ctx->dynperm = 1;
803 break;
804 case Opt_sfu:
805 if (result.negated)
806 ctx->sfu_emul = 0;
807 else
808 ctx->sfu_emul = 1;
809 break;
810 case Opt_noblocksend:
811 ctx->noblocksnd = 1;
812 break;
813 case Opt_noautotune:
814 ctx->noautotune = 1;
815 break;
816 case Opt_nolease:
817 ctx->no_lease = 1;
818 break;
819 case Opt_nodelete:
820 ctx->nodelete = 1;
821 break;
822 case Opt_multichannel:
823 if (result.negated) {
824 ctx->multichannel = false;
825 ctx->max_channels = 1;
826 } else {
827 ctx->multichannel = true;
828 /* if number of channels not specified, default to 2 */
829 if (ctx->max_channels < 2)
830 ctx->max_channels = 2;
831 }
832 break;
833 case Opt_uid:
834 ctx->linux_uid.val = result.uint_32;
835 ctx->uid_specified = true;
836 break;
837 case Opt_cruid:
838 ctx->cred_uid.val = result.uint_32;
839 break;
840 case Opt_backupgid:
841 ctx->backupgid.val = result.uint_32;
842 ctx->backupgid_specified = true;
843 break;
844 case Opt_gid:
845 ctx->linux_gid.val = result.uint_32;
846 ctx->gid_specified = true;
847 break;
848 case Opt_port:
849 ctx->port = result.uint_32;
850 break;
851 case Opt_file_mode:
852 ctx->file_mode = result.uint_32;
853 break;
854 case Opt_dirmode:
855 ctx->dir_mode = result.uint_32;
856 break;
857 case Opt_min_enc_offload:
858 ctx->min_offload = result.uint_32;
859 break;
860 case Opt_blocksize:
861 /*
862 * inode blocksize realistically should never need to be
863 * less than 16K or greater than 16M and default is 1MB.
864 * Note that small inode block sizes (e.g. 64K) can lead
865 * to very poor performance of common tools like cp and scp
866 */
867 if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||
868 (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {
869 cifs_dbg(VFS, "%s: Invalid blocksize\n",
870 __func__);
871 goto cifs_parse_mount_err;
872 }
873 ctx->bsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000874 ctx->got_bsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600875 break;
876 case Opt_rsize:
877 ctx->rsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000878 ctx->got_rsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600879 break;
880 case Opt_wsize:
881 ctx->wsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000882 ctx->got_wsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600883 break;
884 case Opt_actimeo:
885 ctx->actimeo = HZ * result.uint_32;
886 if (ctx->actimeo > CIFS_MAX_ACTIMEO) {
887 cifs_dbg(VFS, "attribute cache timeout too large\n");
888 goto cifs_parse_mount_err;
889 }
890 break;
891 case Opt_echo_interval:
892 ctx->echo_interval = result.uint_32;
893 break;
894 case Opt_snapshot:
895 ctx->snapshot_time = result.uint_32;
896 break;
897 case Opt_max_credits:
898 if (result.uint_32 < 20 || result.uint_32 > 60000) {
899 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
900 __func__);
901 goto cifs_parse_mount_err;
902 }
903 ctx->max_credits = result.uint_32;
904 break;
905 case Opt_max_channels:
906 if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {
907 cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
908 __func__, CIFS_MAX_CHANNELS);
909 goto cifs_parse_mount_err;
910 }
911 ctx->max_channels = result.uint_32;
912 break;
913 case Opt_handletimeout:
914 ctx->handle_timeout = result.uint_32;
915 if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
916 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
917 goto cifs_parse_mount_err;
918 }
919 break;
920 case Opt_source:
921 kfree(ctx->UNC);
922 ctx->UNC = NULL;
923 switch (smb3_parse_devname(param->string, ctx)) {
924 case 0:
925 break;
926 case -ENOMEM:
927 cifs_dbg(VFS, "Unable to allocate memory for devname\n");
928 goto cifs_parse_mount_err;
929 case -EINVAL:
930 cifs_dbg(VFS, "Malformed UNC in devname\n");
931 goto cifs_parse_mount_err;
932 default:
933 cifs_dbg(VFS, "Unknown error parsing devname\n");
934 goto cifs_parse_mount_err;
935 }
936 fc->source = kstrdup(param->string, GFP_KERNEL);
937 if (fc->source == NULL) {
938 cifs_dbg(VFS, "OOM when copying UNC string\n");
939 goto cifs_parse_mount_err;
940 }
941 break;
942 case Opt_user:
943 kfree(ctx->username);
944 ctx->username = NULL;
945 if (strlen(param->string) == 0) {
946 /* null user, ie. anonymous authentication */
947 ctx->nullauth = 1;
948 break;
949 }
950
951 if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) >
952 CIFS_MAX_USERNAME_LEN) {
953 pr_warn("username too long\n");
954 goto cifs_parse_mount_err;
955 }
956 ctx->username = kstrdup(param->string, GFP_KERNEL);
957 if (ctx->username == NULL) {
958 cifs_dbg(VFS, "OOM when copying username string\n");
959 goto cifs_parse_mount_err;
960 }
961 break;
962 case Opt_pass:
963 kfree(ctx->password);
964 ctx->password = NULL;
965 if (strlen(param->string) == 0)
966 break;
967
968 ctx->password = kstrdup(param->string, GFP_KERNEL);
969 if (ctx->password == NULL) {
970 cifs_dbg(VFS, "OOM when copying password string\n");
971 goto cifs_parse_mount_err;
972 }
973 break;
974 case Opt_ip:
975 if (strlen(param->string) == 0) {
976 ctx->got_ip = false;
977 break;
978 }
979 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
980 param->string,
981 strlen(param->string))) {
982 pr_err("bad ip= option (%s)\n", param->string);
983 goto cifs_parse_mount_err;
984 }
985 ctx->got_ip = true;
986 break;
987 case Opt_domain:
988 if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN)
989 == CIFS_MAX_DOMAINNAME_LEN) {
990 pr_warn("domain name too long\n");
991 goto cifs_parse_mount_err;
992 }
993
994 kfree(ctx->domainname);
995 ctx->domainname = kstrdup(param->string, GFP_KERNEL);
996 if (ctx->domainname == NULL) {
997 cifs_dbg(VFS, "OOM when copying domainname string\n");
998 goto cifs_parse_mount_err;
999 }
1000 cifs_dbg(FYI, "Domain name set\n");
1001 break;
1002 case Opt_srcaddr:
1003 if (!cifs_convert_address(
1004 (struct sockaddr *)&ctx->srcaddr,
1005 param->string, strlen(param->string))) {
1006 pr_warn("Could not parse srcaddr: %s\n",
1007 param->string);
1008 goto cifs_parse_mount_err;
1009 }
1010 break;
1011 case Opt_iocharset:
1012 if (strnlen(param->string, 1024) >= 65) {
1013 pr_warn("iocharset name too long\n");
1014 goto cifs_parse_mount_err;
1015 }
1016
1017 if (strncasecmp(param->string, "default", 7) != 0) {
1018 kfree(ctx->iocharset);
1019 ctx->iocharset = kstrdup(param->string, GFP_KERNEL);
1020 if (ctx->iocharset == NULL) {
1021 cifs_dbg(VFS, "OOM when copying iocharset string\n");
1022 goto cifs_parse_mount_err;
1023 }
1024 }
1025 /* if iocharset not set then load_nls_default
1026 * is used by caller
1027 */
1028 cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
1029 break;
1030 case Opt_netbiosname:
1031 memset(ctx->source_rfc1001_name, 0x20,
1032 RFC1001_NAME_LEN);
1033 /*
1034 * FIXME: are there cases in which a comma can
1035 * be valid in workstation netbios name (and
1036 * need special handling)?
1037 */
1038 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1039 /* don't ucase netbiosname for user */
1040 if (param->string[i] == 0)
1041 break;
1042 ctx->source_rfc1001_name[i] = param->string[i];
1043 }
1044 /* The string has 16th byte zero still from
1045 * set at top of the function
1046 */
1047 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1048 pr_warn("netbiosname longer than 15 truncated\n");
1049 break;
1050 case Opt_servern:
1051 /* last byte, type, is 0x20 for servr type */
1052 memset(ctx->target_rfc1001_name, 0x20,
1053 RFC1001_NAME_LEN_WITH_NULL);
1054 /*
1055 * BB are there cases in which a comma can be valid in this
1056 * workstation netbios name (and need special handling)?
1057 */
1058
1059 /* user or mount helper must uppercase the netbios name */
1060 for (i = 0; i < 15; i++) {
1061 if (param->string[i] == 0)
1062 break;
1063 ctx->target_rfc1001_name[i] = param->string[i];
1064 }
1065
1066 /* The string has 16th byte zero still from set at top of function */
1067 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1068 pr_warn("server netbiosname longer than 15 truncated\n");
1069 break;
1070 case Opt_ver:
1071 /* version of mount userspace tools, not dialect */
1072 /* If interface changes in mount.cifs bump to new ver */
1073 if (strncasecmp(param->string, "1", 1) == 0) {
1074 if (strlen(param->string) > 1) {
1075 pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
1076 param->string);
1077 goto cifs_parse_mount_err;
1078 }
1079 /* This is the default */
1080 break;
1081 }
1082 /* For all other value, error */
1083 pr_warn("Invalid mount helper version specified\n");
1084 goto cifs_parse_mount_err;
1085 case Opt_vers:
1086 /* protocol version (dialect) */
1087 if (cifs_parse_smb_version(param->string, ctx, is_smb3) != 0)
1088 goto cifs_parse_mount_err;
1089 ctx->got_version = true;
1090 break;
1091 case Opt_sec:
1092 if (cifs_parse_security_flavors(param->string, ctx) != 0)
1093 goto cifs_parse_mount_err;
1094 break;
1095 case Opt_cache:
1096 if (cifs_parse_cache_flavor(param->string, ctx) != 0)
1097 goto cifs_parse_mount_err;
1098 break;
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001099 case Opt_witness:
1100#ifndef CONFIG_CIFS_SWN_UPCALL
1101 cifs_dbg(VFS, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
1102 goto cifs_parse_mount_err;
1103#endif
1104 ctx->witness = true;
Steve Frenchdd538032020-12-14 20:15:12 -06001105 pr_warn_once("Witness protocol support is experimental\n");
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001106 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001107 case Opt_rootfs:
1108#ifdef CONFIG_CIFS_ROOT
1109 ctx->rootfs = true;
1110#endif
1111 break;
1112 case Opt_posixpaths:
1113 if (result.negated)
1114 ctx->posix_paths = 0;
1115 else
1116 ctx->posix_paths = 1;
1117 break;
1118 case Opt_unix:
1119 if (result.negated)
1120 ctx->linux_ext = 0;
1121 else
1122 ctx->no_linux_ext = 1;
1123 break;
1124 case Opt_nocase:
1125 ctx->nocase = 1;
1126 break;
1127 case Opt_brl:
1128 if (result.negated) {
1129 /*
1130 * turn off mandatory locking in mode
1131 * if remote locking is turned off since the
1132 * local vfs will do advisory
1133 */
1134 if (ctx->file_mode ==
1135 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1136 ctx->file_mode = S_IALLUGO;
1137 ctx->nobrl = 1;
1138 } else
1139 ctx->nobrl = 0;
1140 break;
1141 case Opt_handlecache:
1142 if (result.negated)
1143 ctx->nohandlecache = 1;
1144 else
1145 ctx->nohandlecache = 0;
1146 break;
1147 case Opt_forcemandatorylock:
1148 ctx->mand_lock = 1;
1149 break;
1150 case Opt_setuids:
1151 ctx->setuids = result.negated;
1152 break;
1153 case Opt_intr:
1154 ctx->intr = !result.negated;
1155 break;
1156 case Opt_setuidfromacl:
1157 ctx->setuidfromacl = 1;
1158 break;
1159 case Opt_strictsync:
1160 ctx->nostrictsync = result.negated;
1161 break;
1162 case Opt_serverino:
1163 ctx->server_ino = !result.negated;
1164 break;
1165 case Opt_rwpidforward:
1166 ctx->rwpidforward = 1;
1167 break;
1168 case Opt_modesid:
1169 ctx->mode_ace = 1;
1170 break;
1171 case Opt_cifsacl:
1172 ctx->cifs_acl = !result.negated;
1173 break;
1174 case Opt_acl:
1175 ctx->no_psx_acl = result.negated;
1176 break;
1177 case Opt_locallease:
1178 ctx->local_lease = 1;
1179 break;
1180 case Opt_sign:
1181 ctx->sign = true;
1182 break;
1183 case Opt_ignore_signature:
1184 ctx->sign = true;
1185 ctx->ignore_signature = true;
1186 break;
1187 case Opt_seal:
1188 /* we do not do the following in secFlags because seal
1189 * is a per tree connection (mount) not a per socket
1190 * or per-smb connection option in the protocol
1191 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1192 */
1193 ctx->seal = 1;
1194 break;
1195 case Opt_noac:
1196 pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1197 break;
1198 case Opt_fsc:
1199#ifndef CONFIG_CIFS_FSCACHE
1200 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
1201 goto cifs_parse_mount_err;
1202#endif
1203 ctx->fsc = true;
1204 break;
1205 case Opt_mfsymlinks:
1206 ctx->mfsymlinks = true;
1207 break;
1208 case Opt_multiuser:
1209 ctx->multiuser = true;
1210 break;
1211 case Opt_sloppy:
1212 ctx->sloppy = true;
1213 break;
1214 case Opt_nosharesock:
1215 ctx->nosharesock = true;
1216 break;
1217 case Opt_persistent:
1218 if (result.negated) {
Steve French27cf9482020-12-16 01:22:54 -06001219 ctx->nopersistent = true;
1220 if (ctx->persistent) {
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001221 cifs_dbg(VFS,
1222 "persistenthandles mount options conflict\n");
1223 goto cifs_parse_mount_err;
1224 }
1225 } else {
Steve French27cf9482020-12-16 01:22:54 -06001226 ctx->persistent = true;
1227 if ((ctx->nopersistent) || (ctx->resilient)) {
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001228 cifs_dbg(VFS,
1229 "persistenthandles mount options conflict\n");
1230 goto cifs_parse_mount_err;
1231 }
1232 }
1233 break;
1234 case Opt_resilient:
1235 if (result.negated) {
1236 ctx->resilient = false; /* already the default */
1237 } else {
1238 ctx->resilient = true;
1239 if (ctx->persistent) {
1240 cifs_dbg(VFS,
1241 "persistenthandles mount options conflict\n");
1242 goto cifs_parse_mount_err;
1243 }
1244 }
1245 break;
1246 case Opt_domainauto:
1247 ctx->domainauto = true;
1248 break;
1249 case Opt_rdma:
1250 ctx->rdma = true;
1251 break;
1252 }
1253
1254 return 0;
1255
1256 cifs_parse_mount_err:
1257 return 1;
1258}
1259
1260int smb3_init_fs_context(struct fs_context *fc)
1261{
1262 struct smb3_fs_context *ctx;
1263 char *nodename = utsname()->nodename;
1264 int i;
1265
1266 ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
1267 if (unlikely(!ctx))
1268 return -ENOMEM;
1269
1270 /*
1271 * does not have to be perfect mapping since field is
1272 * informational, only used for servers that do not support
1273 * port 445 and it can be overridden at mount time
1274 */
1275 memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1276 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
1277 ctx->source_rfc1001_name[i] = toupper(nodename[i]);
1278
1279 ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1280 /*
1281 * null target name indicates to use *SMBSERVR default called name
1282 * if we end up sending RFC1001 session initialize
1283 */
1284 ctx->target_rfc1001_name[0] = 0;
1285 ctx->cred_uid = current_uid();
1286 ctx->linux_uid = current_uid();
1287 ctx->linux_gid = current_gid();
1288 ctx->bsize = 1024 * 1024; /* can improve cp performance significantly */
1289
1290 /*
1291 * default to SFM style remapping of seven reserved characters
1292 * unless user overrides it or we negotiate CIFS POSIX where
1293 * it is unnecessary. Can not simultaneously use more than one mapping
1294 * since then readdir could list files that open could not open
1295 */
1296 ctx->remap = true;
1297
1298 /* default to only allowing write access to owner of the mount */
1299 ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1300
1301 /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1302 /* default is always to request posix paths. */
1303 ctx->posix_paths = 1;
1304 /* default to using server inode numbers where available */
1305 ctx->server_ino = 1;
1306
1307 /* default is to use strict cifs caching semantics */
1308 ctx->strict_io = true;
1309
1310 ctx->actimeo = CIFS_DEF_ACTIMEO;
1311
1312 /* Most clients set timeout to 0, allows server to use its default */
1313 ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1314
1315 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1316 ctx->ops = &smb30_operations;
1317 ctx->vals = &smbdefault_values;
1318
1319 ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1320
1321 /* default to no multichannel (single server connection) */
1322 ctx->multichannel = false;
1323 ctx->max_channels = 1;
1324
1325 ctx->backupuid_specified = false; /* no backup intent for a user */
1326 ctx->backupgid_specified = false; /* no backup intent for a group */
1327
1328/*
1329 * short int override_uid = -1;
1330 * short int override_gid = -1;
1331 * char *nodename = strdup(utsname()->nodename);
1332 * struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
1333 */
1334
1335 fc->fs_private = ctx;
1336 fc->ops = &smb3_fs_context_ops;
1337 return 0;
1338}
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001339
1340void
1341smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
1342{
1343 if (ctx == NULL)
1344 return;
1345
1346 /*
1347 * Make sure this stays in sync with smb3_fs_context_dup()
1348 */
1349 kfree(ctx->mount_options);
1350 ctx->mount_options = NULL;
1351 kfree(ctx->username);
1352 ctx->username = NULL;
1353 kfree_sensitive(ctx->password);
1354 ctx->password = NULL;
1355 kfree(ctx->UNC);
1356 ctx->UNC = NULL;
1357 kfree(ctx->domainname);
1358 ctx->domainname = NULL;
1359 kfree(ctx->nodename);
1360 ctx->nodename = NULL;
1361 kfree(ctx->iocharset);
1362 ctx->iocharset = NULL;
1363 kfree(ctx->prepath);
1364 ctx->prepath = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001365}
1366
1367void
1368smb3_cleanup_fs_context(struct smb3_fs_context *ctx)
1369{
1370 if (!ctx)
1371 return;
1372 smb3_cleanup_fs_context_contents(ctx);
1373 kfree(ctx);
1374}
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001375
1376void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
1377{
1378 struct smb3_fs_context *ctx = cifs_sb->ctx;
1379
1380 if (ctx->nodfs)
1381 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
1382 else
1383 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS;
1384
1385 if (ctx->noperm)
1386 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1387 else
1388 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM;
1389
1390 if (ctx->setuids)
1391 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1392 else
1393 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID;
1394
1395 if (ctx->setuidfromacl)
1396 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
1397 else
1398 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL;
1399
1400 if (ctx->server_ino)
1401 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1402 else
1403 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
1404
1405 if (ctx->remap)
1406 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
1407 else
1408 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR;
1409
1410 if (ctx->sfu_remap)
1411 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1412 else
1413 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
1414
1415 if (ctx->no_xattr)
1416 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1417 else
1418 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR;
1419
1420 if (ctx->sfu_emul)
1421 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1422 else
1423 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL;
1424
1425 if (ctx->nobrl)
1426 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1427 else
1428 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL;
1429
1430 if (ctx->nohandlecache)
1431 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
1432 else
1433 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
1434
1435 if (ctx->nostrictsync)
1436 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
1437 else
1438 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC;
1439
1440 if (ctx->mand_lock)
1441 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
1442 else
1443 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL;
1444
1445 if (ctx->rwpidforward)
1446 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
1447 else
1448 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD;
1449
1450 if (ctx->mode_ace)
1451 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
1452 else
1453 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID;
1454
1455 if (ctx->cifs_acl)
1456 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1457 else
1458 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL;
1459
1460 if (ctx->backupuid_specified)
1461 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
1462 else
1463 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
1464
1465 if (ctx->backupgid_specified)
1466 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
1467 else
1468 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
1469
1470 if (ctx->override_uid)
1471 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
1472 else
1473 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID;
1474
1475 if (ctx->override_gid)
1476 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
1477 else
1478 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID;
1479
1480 if (ctx->dynperm)
1481 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
1482 else
1483 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM;
1484
1485 if (ctx->fsc)
1486 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
1487 else
1488 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE;
1489
1490 if (ctx->multiuser)
1491 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
1492 CIFS_MOUNT_NO_PERM);
1493 else
1494 cifs_sb->mnt_cifs_flags &= ~(CIFS_MOUNT_MULTIUSER |
1495 CIFS_MOUNT_NO_PERM);
1496
1497 if (ctx->strict_io)
1498 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
1499 else
1500 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO;
1501
1502 if (ctx->direct_io)
1503 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1504 else
1505 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO;
1506
1507 if (ctx->mfsymlinks)
1508 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
1509 else
1510 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS;
1511 if (ctx->mfsymlinks) {
1512 if (ctx->sfu_emul) {
1513 /*
1514 * Our SFU ("Services for Unix" emulation does not allow
1515 * creating symlinks but does allow reading existing SFU
1516 * symlinks (it does allow both creating and reading SFU
1517 * style mknod and FIFOs though). When "mfsymlinks" and
1518 * "sfu" are both enabled at the same time, it allows
1519 * reading both types of symlinks, but will only create
1520 * them with mfsymlinks format. This allows better
1521 * Apple compatibility (probably better for Samba too)
1522 * while still recognizing old Windows style symlinks.
1523 */
1524 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
1525 }
1526 }
1527
1528 return;
1529}