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