blob: 6a179ae753c118bdfc3fa3b78865431821baa60e [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>
Paulo Alcantarab6236612021-07-16 03:26:41 -030016#ifdef CONFIG_CIFS_DFS_UPCALL
17#include "dfs_cache.h"
18#endif
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -060019*/
20
21#include <linux/ctype.h>
22#include <linux/fs_context.h>
23#include <linux/fs_parser.h>
24#include <linux/fs.h>
25#include <linux/mount.h>
26#include <linux/parser.h>
27#include <linux/utsname.h>
28#include "cifsfs.h"
29#include "cifspdu.h"
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100030#include "cifsglob.h"
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +100031#include "cifsproto.h"
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -060032#include "cifs_unicode.h"
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100033#include "cifs_debug.h"
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -060034#include "cifs_fs_sb.h"
35#include "ntlmssp.h"
36#include "nterr.h"
37#include "rfc1002pdu.h"
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100038#include "fs_context.h"
39
Ronnie Sahlberg555782a2020-10-21 12:10:44 +100040static const match_table_t cifs_smb_version_tokens = {
41 { Smb_1, SMB1_VERSION_STRING },
42 { Smb_20, SMB20_VERSION_STRING},
43 { Smb_21, SMB21_VERSION_STRING },
44 { Smb_30, SMB30_VERSION_STRING },
45 { Smb_302, SMB302_VERSION_STRING },
46 { Smb_302, ALT_SMB302_VERSION_STRING },
47 { Smb_311, SMB311_VERSION_STRING },
48 { Smb_311, ALT_SMB311_VERSION_STRING },
49 { Smb_3any, SMB3ANY_VERSION_STRING },
50 { Smb_default, SMBDEFAULT_VERSION_STRING },
51 { Smb_version_err, NULL }
52};
53
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100054static const match_table_t cifs_secflavor_tokens = {
55 { Opt_sec_krb5, "krb5" },
56 { Opt_sec_krb5i, "krb5i" },
57 { Opt_sec_krb5p, "krb5p" },
58 { Opt_sec_ntlmsspi, "ntlmsspi" },
59 { Opt_sec_ntlmssp, "ntlmssp" },
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100060 { Opt_sec_ntlmv2, "nontlm" },
61 { Opt_sec_ntlmv2, "ntlmv2" },
62 { Opt_sec_ntlmv2i, "ntlmv2i" },
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100063 { 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),
Steve French7ae5e582021-10-14 15:54:26 -0500119 fsparam_flag_no("tcpnodelay", Opt_tcp_nodelay),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600120 fsparam_flag("domainauto", Opt_domainauto),
121 fsparam_flag("rdma", Opt_rdma),
122 fsparam_flag("modesid", Opt_modesid),
Steve French27cf9482020-12-16 01:22:54 -0600123 fsparam_flag("modefromsid", Opt_modesid),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600124 fsparam_flag("rootfs", Opt_rootfs),
125 fsparam_flag("compress", Opt_compress),
Samuel Cabrero0ac4e292020-12-11 22:59:29 -0600126 fsparam_flag("witness", Opt_witness),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600127
128 /* Mount options which take numeric value */
129 fsparam_u32("backupuid", Opt_backupuid),
130 fsparam_u32("backupgid", Opt_backupgid),
131 fsparam_u32("uid", Opt_uid),
132 fsparam_u32("cruid", Opt_cruid),
133 fsparam_u32("gid", Opt_gid),
134 fsparam_u32("file_mode", Opt_file_mode),
135 fsparam_u32("dirmode", Opt_dirmode),
136 fsparam_u32("dir_mode", Opt_dirmode),
137 fsparam_u32("port", Opt_port),
138 fsparam_u32("min_enc_offload", Opt_min_enc_offload),
Steve French27cf9482020-12-16 01:22:54 -0600139 fsparam_u32("esize", Opt_min_enc_offload),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600140 fsparam_u32("bsize", Opt_blocksize),
Steve Frenchb8d64f82021-04-24 21:46:23 -0500141 fsparam_u32("rasize", Opt_rasize),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600142 fsparam_u32("rsize", Opt_rsize),
143 fsparam_u32("wsize", Opt_wsize),
144 fsparam_u32("actimeo", Opt_actimeo),
Steve French4c9f9482021-02-23 15:50:57 -0600145 fsparam_u32("acdirmax", Opt_acdirmax),
Steve French57804642021-02-24 12:12:53 -0600146 fsparam_u32("acregmax", Opt_acregmax),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600147 fsparam_u32("echo_interval", Opt_echo_interval),
148 fsparam_u32("max_credits", Opt_max_credits),
149 fsparam_u32("handletimeout", Opt_handletimeout),
150 fsparam_u32("snapshot", Opt_snapshot),
151 fsparam_u32("max_channels", Opt_max_channels),
152
153 /* Mount options which take string value */
154 fsparam_string("source", Opt_source),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600155 fsparam_string("user", Opt_user),
156 fsparam_string("username", Opt_user),
157 fsparam_string("pass", Opt_pass),
158 fsparam_string("password", Opt_pass),
159 fsparam_string("ip", Opt_ip),
160 fsparam_string("addr", Opt_ip),
161 fsparam_string("domain", Opt_domain),
162 fsparam_string("dom", Opt_domain),
163 fsparam_string("srcaddr", Opt_srcaddr),
164 fsparam_string("iocharset", Opt_iocharset),
165 fsparam_string("netbiosname", Opt_netbiosname),
166 fsparam_string("servern", Opt_servern),
167 fsparam_string("ver", Opt_ver),
168 fsparam_string("vers", Opt_vers),
169 fsparam_string("sec", Opt_sec),
170 fsparam_string("cache", Opt_cache),
171
172 /* Arguments that should be ignored */
173 fsparam_flag("guest", Opt_ignore),
174 fsparam_flag("noatime", Opt_ignore),
175 fsparam_flag("relatime", Opt_ignore),
176 fsparam_flag("_netdev", Opt_ignore),
177 fsparam_flag_no("suid", Opt_ignore),
178 fsparam_flag_no("exec", Opt_ignore),
179 fsparam_flag_no("dev", Opt_ignore),
180 fsparam_flag_no("mand", Opt_ignore),
Adam Harvey19d51582021-01-27 13:44:35 -0800181 fsparam_flag_no("auto", Opt_ignore),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600182 fsparam_string("cred", Opt_ignore),
183 fsparam_string("credentials", Opt_ignore),
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000184 /*
185 * UNC and prefixpath is now extracted from Opt_source
186 * in the new mount API so we can just ignore them going forward.
187 */
188 fsparam_string("unc", Opt_ignore),
Steve Frenchc9b8cd62021-01-28 11:20:22 -0600189 fsparam_string("prefixpath", Opt_ignore),
Dmitry Osipenko427c4f02020-12-14 14:37:45 +0300190 {}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600191};
192
Aurelien Apteld9a86922021-03-01 19:32:09 +0100193static int
194cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000195{
196
197 substring_t args[MAX_OPT_ARGS];
198
199 /*
200 * With mount options, the last one should win. Reset any existing
201 * settings back to default.
202 */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600203 ctx->sectype = Unspecified;
204 ctx->sign = false;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000205
206 switch (match_token(value, cifs_secflavor_tokens, args)) {
207 case Opt_sec_krb5p:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100208 cifs_errorf(fc, "sec=krb5p is not supported!\n");
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000209 return 1;
210 case Opt_sec_krb5i:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600211 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000212 fallthrough;
213 case Opt_sec_krb5:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600214 ctx->sectype = Kerberos;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000215 break;
216 case Opt_sec_ntlmsspi:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600217 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000218 fallthrough;
219 case Opt_sec_ntlmssp:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600220 ctx->sectype = RawNTLMSSP;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000221 break;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000222 case Opt_sec_ntlmv2i:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600223 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000224 fallthrough;
225 case Opt_sec_ntlmv2:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600226 ctx->sectype = NTLMv2;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000227 break;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000228 case Opt_sec_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600229 ctx->nullauth = 1;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000230 break;
231 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100232 cifs_errorf(fc, "bad security option: %s\n", value);
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000233 return 1;
234 }
235
236 return 0;
237}
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000238
239static const match_table_t cifs_cacheflavor_tokens = {
240 { Opt_cache_loose, "loose" },
241 { Opt_cache_strict, "strict" },
242 { Opt_cache_none, "none" },
243 { Opt_cache_ro, "ro" },
244 { Opt_cache_rw, "singleclient" },
245 { Opt_cache_err, NULL }
246};
247
Aurelien Apteld9a86922021-03-01 19:32:09 +0100248static int
249cifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000250{
251 substring_t args[MAX_OPT_ARGS];
252
253 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
254 case Opt_cache_loose:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600255 ctx->direct_io = false;
256 ctx->strict_io = false;
257 ctx->cache_ro = false;
258 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000259 break;
260 case Opt_cache_strict:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600261 ctx->direct_io = false;
262 ctx->strict_io = true;
263 ctx->cache_ro = false;
264 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000265 break;
266 case Opt_cache_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600267 ctx->direct_io = true;
268 ctx->strict_io = false;
269 ctx->cache_ro = false;
270 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000271 break;
272 case Opt_cache_ro:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600273 ctx->direct_io = false;
274 ctx->strict_io = false;
275 ctx->cache_ro = true;
276 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000277 break;
278 case Opt_cache_rw:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600279 ctx->direct_io = false;
280 ctx->strict_io = false;
281 ctx->cache_ro = false;
282 ctx->cache_rw = true;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000283 break;
284 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100285 cifs_errorf(fc, "bad cache= option: %s\n", value);
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000286 return 1;
287 }
288 return 0;
289}
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000290
291#define DUP_CTX_STR(field) \
292do { \
293 if (ctx->field) { \
294 new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC); \
295 if (new_ctx->field == NULL) { \
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000296 smb3_cleanup_fs_context_contents(new_ctx); \
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000297 return -ENOMEM; \
298 } \
299 } \
300} while (0)
301
302int
303smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)
304{
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000305 memcpy(new_ctx, ctx, sizeof(*ctx));
306 new_ctx->prepath = NULL;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600307 new_ctx->mount_options = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000308 new_ctx->nodename = NULL;
309 new_ctx->username = NULL;
310 new_ctx->password = NULL;
Paulo Alcantara869da642021-11-12 14:53:36 -0300311 new_ctx->server_hostname = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000312 new_ctx->domainname = NULL;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000313 new_ctx->workstation_name = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000314 new_ctx->UNC = NULL;
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000315 new_ctx->source = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000316 new_ctx->iocharset = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000317 /*
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000318 * Make sure to stay in sync with smb3_cleanup_fs_context_contents()
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000319 */
320 DUP_CTX_STR(prepath);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600321 DUP_CTX_STR(mount_options);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000322 DUP_CTX_STR(username);
323 DUP_CTX_STR(password);
Shyam Prasad N7be32482021-10-14 11:52:39 +0000324 DUP_CTX_STR(server_hostname);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000325 DUP_CTX_STR(UNC);
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000326 DUP_CTX_STR(source);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000327 DUP_CTX_STR(domainname);
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000328 DUP_CTX_STR(workstation_name);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000329 DUP_CTX_STR(nodename);
330 DUP_CTX_STR(iocharset);
331
Menglong Dongc13e7af2021-01-12 01:13:40 -0800332 return 0;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000333}
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000334
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600335static int
Aurelien Apteld9a86922021-03-01 19:32:09 +0100336cifs_parse_smb_version(struct fs_context *fc, char *value, struct smb3_fs_context *ctx, bool is_smb3)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600337{
338 substring_t args[MAX_OPT_ARGS];
339
340 switch (match_token(value, cifs_smb_version_tokens, args)) {
341#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
342 case Smb_1:
343 if (disable_legacy_dialects) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100344 cifs_errorf(fc, "mount with legacy dialect disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600345 return 1;
346 }
347 if (is_smb3) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100348 cifs_errorf(fc, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600349 return 1;
350 }
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100351 cifs_errorf(fc, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600352 ctx->ops = &smb1_operations;
353 ctx->vals = &smb1_values;
354 break;
355 case Smb_20:
356 if (disable_legacy_dialects) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100357 cifs_errorf(fc, "mount with legacy dialect disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600358 return 1;
359 }
360 if (is_smb3) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100361 cifs_errorf(fc, "vers=2.0 not permitted when mounting with smb3\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600362 return 1;
363 }
364 ctx->ops = &smb20_operations;
365 ctx->vals = &smb20_values;
366 break;
367#else
368 case Smb_1:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100369 cifs_errorf(fc, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600370 return 1;
371 case Smb_20:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100372 cifs_errorf(fc, "vers=2.0 mount not permitted when legacy dialects disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600373 return 1;
374#endif /* CIFS_ALLOW_INSECURE_LEGACY */
375 case Smb_21:
376 ctx->ops = &smb21_operations;
377 ctx->vals = &smb21_values;
378 break;
379 case Smb_30:
380 ctx->ops = &smb30_operations;
381 ctx->vals = &smb30_values;
382 break;
383 case Smb_302:
384 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
385 ctx->vals = &smb302_values;
386 break;
387 case Smb_311:
388 ctx->ops = &smb311_operations;
389 ctx->vals = &smb311_values;
390 break;
391 case Smb_3any:
392 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
393 ctx->vals = &smb3any_values;
394 break;
395 case Smb_default:
Steve French6dffa4c2021-02-02 00:03:58 -0600396 ctx->ops = &smb30_operations;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600397 ctx->vals = &smbdefault_values;
398 break;
399 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100400 cifs_errorf(fc, "Unknown vers= option specified: %s\n", value);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600401 return 1;
402 }
403 return 0;
404}
405
Ronnie Sahlberg0d4873f2021-01-28 21:35:10 -0600406int smb3_parse_opt(const char *options, const char *key, char **val)
407{
408 int rc = -ENOENT;
409 char *opts, *orig, *p;
410
411 orig = opts = kstrdup(options, GFP_KERNEL);
412 if (!opts)
413 return -ENOMEM;
414
415 while ((p = strsep(&opts, ","))) {
416 char *nval;
417
418 if (!*p)
419 continue;
420 if (strncasecmp(p, key, strlen(key)))
421 continue;
422 nval = strchr(p, '=');
423 if (nval) {
424 if (nval == p)
425 continue;
426 *nval++ = 0;
Al Viro8d767222021-03-05 15:02:34 -0500427 *val = kstrdup(nval, GFP_KERNEL);
Ronnie Sahlberg0d4873f2021-01-28 21:35:10 -0600428 rc = !*val ? -ENOMEM : 0;
429 goto out;
430 }
431 }
432out:
433 kfree(orig);
434 return rc;
435}
436
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000437/*
438 * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath
439 * fields with the result. Returns 0 on success and an error otherwise
440 * (e.g. ENOMEM or EINVAL)
441 */
442int
443smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
444{
445 char *pos;
446 const char *delims = "/\\";
447 size_t len;
448
449 if (unlikely(!devname || !*devname)) {
450 cifs_dbg(VFS, "Device name not specified\n");
451 return -EINVAL;
452 }
453
454 /* make sure we have a valid UNC double delimiter prefix */
455 len = strspn(devname, delims);
456 if (len != 2)
457 return -EINVAL;
458
459 /* find delimiter between host and sharename */
460 pos = strpbrk(devname + 2, delims);
461 if (!pos)
462 return -EINVAL;
463
Shyam Prasad N7be32482021-10-14 11:52:39 +0000464 /* record the server hostname */
Paulo Alcantara869da642021-11-12 14:53:36 -0300465 kfree(ctx->server_hostname);
Shyam Prasad N7be32482021-10-14 11:52:39 +0000466 ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL);
467 if (!ctx->server_hostname)
468 return -ENOMEM;
469
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000470 /* skip past delimiter */
471 ++pos;
472
473 /* now go until next delimiter or end of string */
474 len = strcspn(pos, delims);
475
476 /* move "pos" up to delimiter or NULL */
477 pos += len;
Paulo Alcantara5c1acf32021-05-03 11:55:26 -0300478 kfree(ctx->UNC);
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000479 ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
480 if (!ctx->UNC)
481 return -ENOMEM;
482
483 convert_delimiter(ctx->UNC, '\\');
484
485 /* skip any delimiter */
486 if (*pos == '/' || *pos == '\\')
487 pos++;
488
Paulo Alcantara5c1acf32021-05-03 11:55:26 -0300489 kfree(ctx->prepath);
490 ctx->prepath = NULL;
491
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000492 /* If pos is NULL then no prepath */
493 if (!*pos)
494 return 0;
495
496 ctx->prepath = kstrdup(pos, GFP_KERNEL);
497 if (!ctx->prepath)
498 return -ENOMEM;
499
500 return 0;
501}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600502
503static void smb3_fs_context_free(struct fs_context *fc);
504static int smb3_fs_context_parse_param(struct fs_context *fc,
505 struct fs_parameter *param);
506static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
507 void *data);
508static int smb3_get_tree(struct fs_context *fc);
509static int smb3_reconfigure(struct fs_context *fc);
510
511static const struct fs_context_operations smb3_fs_context_ops = {
512 .free = smb3_fs_context_free,
513 .parse_param = smb3_fs_context_parse_param,
514 .parse_monolithic = smb3_fs_context_parse_monolithic,
515 .get_tree = smb3_get_tree,
516 .reconfigure = smb3_reconfigure,
517};
518
519/*
520 * Parse a monolithic block of data from sys_mount().
521 * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data
522 * @ctx: The superblock configuration to fill in.
523 * @data: The data to parse
524 *
525 * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be
526 * called from the ->monolithic_mount_data() fs_context operation.
527 *
528 * Returns 0 on success or the error returned by the ->parse_option() fs_context
529 * operation on failure.
530 */
531static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
532 void *data)
533{
534 struct smb3_fs_context *ctx = smb3_fc2context(fc);
535 char *options = data, *key;
536 int ret = 0;
537
538 if (!options)
539 return 0;
540
541 ctx->mount_options = kstrdup(data, GFP_KERNEL);
542 if (ctx->mount_options == NULL)
543 return -ENOMEM;
544
545 ret = security_sb_eat_lsm_opts(options, &fc->security);
546 if (ret)
547 return ret;
548
549 /* BB Need to add support for sep= here TBD */
550 while ((key = strsep(&options, ",")) != NULL) {
Ronnie Sahlbergd08395a2021-02-25 17:36:27 +1000551 size_t len;
552 char *value;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600553
Ronnie Sahlbergd08395a2021-02-25 17:36:27 +1000554 if (*key == 0)
555 break;
556
557 /* Check if following character is the deliminator If yes,
558 * we have encountered a double deliminator reset the NULL
559 * character to the deliminator
560 */
561 while (options && options[0] == ',') {
562 len = strlen(key);
563 strcpy(key + len, options);
564 options = strchr(options, ',');
565 if (options)
566 *options++ = 0;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600567 }
Ronnie Sahlbergd08395a2021-02-25 17:36:27 +1000568
569
570 len = 0;
571 value = strchr(key, '=');
572 if (value) {
573 if (value == key)
574 continue;
575 *value++ = 0;
576 len = strlen(value);
577 }
578
579 ret = vfs_parse_fs_string(fc, key, value, len);
580 if (ret < 0)
581 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600582 }
583
584 return ret;
585}
586
587/*
588 * Validate the preparsed information in the config.
589 */
590static int smb3_fs_context_validate(struct fs_context *fc)
591{
592 struct smb3_fs_context *ctx = smb3_fc2context(fc);
593
594 if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100595 cifs_errorf(fc, "SMB Direct requires Version >=3.0\n");
Steve Frenchbd2f0b42021-01-28 16:43:03 -0600596 return -EOPNOTSUPP;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600597 }
598
599#ifndef CONFIG_KEYS
600 /* Muliuser mounts require CONFIG_KEYS support */
601 if (ctx->multiuser) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100602 cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600603 return -1;
604 }
605#endif
606
607 if (ctx->got_version == false)
608 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");
609
610
611 if (!ctx->UNC) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100612 cifs_errorf(fc, "CIFS mount error: No usable UNC path provided in device string!\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600613 return -1;
614 }
615
616 /* make sure UNC has a share name */
617 if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100618 cifs_errorf(fc, "Malformed UNC. Unable to find share name.\n");
Steve Frenchbd2f0b42021-01-28 16:43:03 -0600619 return -ENOENT;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600620 }
621
622 if (!ctx->got_ip) {
623 int len;
624 const char *slash;
625
626 /* No ip= option specified? Try to get it from UNC */
627 /* Use the address part of the UNC. */
628 slash = strchr(&ctx->UNC[2], '\\');
629 len = slash - &ctx->UNC[2];
630 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
631 &ctx->UNC[2], len)) {
632 pr_err("Unable to determine destination address\n");
Steve Frenchbd2f0b42021-01-28 16:43:03 -0600633 return -EHOSTUNREACH;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600634 }
635 }
636
637 /* set the port that we got earlier */
638 cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
639
640 if (ctx->override_uid && !ctx->uid_specified) {
641 ctx->override_uid = 0;
642 pr_notice("ignoring forceuid mount option specified with no uid= option\n");
643 }
644
645 if (ctx->override_gid && !ctx->gid_specified) {
646 ctx->override_gid = 0;
647 pr_notice("ignoring forcegid mount option specified with no gid= option\n");
648 }
649
650 return 0;
651}
652
653static int smb3_get_tree_common(struct fs_context *fc)
654{
655 struct smb3_fs_context *ctx = smb3_fc2context(fc);
656 struct dentry *root;
657 int rc = 0;
658
659 root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);
660 if (IS_ERR(root))
661 return PTR_ERR(root);
662
663 fc->root = root;
664
665 return rc;
666}
667
668/*
669 * Create an SMB3 superblock from the parameters passed.
670 */
671static int smb3_get_tree(struct fs_context *fc)
672{
673 int err = smb3_fs_context_validate(fc);
674
675 if (err)
676 return err;
677 return smb3_get_tree_common(fc);
678}
679
680static void smb3_fs_context_free(struct fs_context *fc)
681{
682 struct smb3_fs_context *ctx = smb3_fc2context(fc);
683
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000684 smb3_cleanup_fs_context(ctx);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600685}
686
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000687/*
688 * Compare the old and new proposed context during reconfigure
689 * and check if the changes are compatible.
690 */
Aurelien Apteld9a86922021-03-01 19:32:09 +0100691static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
692 struct smb3_fs_context *new_ctx,
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000693 struct smb3_fs_context *old_ctx)
694{
Ronnie Sahlberg531f03b2020-12-14 16:40:23 +1000695 if (new_ctx->posix_paths != old_ctx->posix_paths) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100696 cifs_errorf(fc, "can not change posixpaths during remount\n");
Ronnie Sahlberg531f03b2020-12-14 16:40:23 +1000697 return -EINVAL;
698 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000699 if (new_ctx->sectype != old_ctx->sectype) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100700 cifs_errorf(fc, "can not change sec during remount\n");
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000701 return -EINVAL;
702 }
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000703 if (new_ctx->multiuser != old_ctx->multiuser) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100704 cifs_errorf(fc, "can not change multiuser during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000705 return -EINVAL;
706 }
707 if (new_ctx->UNC &&
708 (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100709 cifs_errorf(fc, "can not change UNC during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000710 return -EINVAL;
711 }
712 if (new_ctx->username &&
713 (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100714 cifs_errorf(fc, "can not change username during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000715 return -EINVAL;
716 }
717 if (new_ctx->password &&
718 (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100719 cifs_errorf(fc, "can not change password during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000720 return -EINVAL;
721 }
722 if (new_ctx->domainname &&
723 (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100724 cifs_errorf(fc, "can not change domainname during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000725 return -EINVAL;
726 }
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000727 if (new_ctx->workstation_name &&
728 (!old_ctx->workstation_name || strcmp(new_ctx->workstation_name, old_ctx->workstation_name))) {
729 cifs_errorf(fc, "can not change workstation_name during remount\n");
730 return -EINVAL;
731 }
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000732 if (new_ctx->nodename &&
733 (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100734 cifs_errorf(fc, "can not change nodename during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000735 return -EINVAL;
736 }
737 if (new_ctx->iocharset &&
738 (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100739 cifs_errorf(fc, "can not change iocharset during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000740 return -EINVAL;
741 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000742
743 return 0;
744}
745
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000746#define STEAL_STRING(cifs_sb, ctx, field) \
747do { \
748 kfree(ctx->field); \
749 ctx->field = cifs_sb->ctx->field; \
750 cifs_sb->ctx->field = NULL; \
751} while (0)
752
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600753static int smb3_reconfigure(struct fs_context *fc)
754{
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000755 struct smb3_fs_context *ctx = smb3_fc2context(fc);
756 struct dentry *root = fc->root;
757 struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
758 int rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600759
Aurelien Apteld9a86922021-03-01 19:32:09 +0100760 rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000761 if (rc)
762 return rc;
763
764 /*
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000765 * We can not change UNC/username/password/domainname/
766 * workstation_name/nodename/iocharset
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000767 * during reconnect so ignore what we have in the new context and
768 * just use what we already have in cifs_sb->ctx.
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000769 */
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000770 STEAL_STRING(cifs_sb, ctx, UNC);
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000771 STEAL_STRING(cifs_sb, ctx, source);
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000772 STEAL_STRING(cifs_sb, ctx, username);
773 STEAL_STRING(cifs_sb, ctx, password);
774 STEAL_STRING(cifs_sb, ctx, domainname);
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000775 STEAL_STRING(cifs_sb, ctx, workstation_name);
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000776 STEAL_STRING(cifs_sb, ctx, nodename);
777 STEAL_STRING(cifs_sb, ctx, iocharset);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000778
Steve French2d060492020-12-16 18:04:27 -0600779 /* if rsize or wsize not passed in on remount, use previous values */
780 if (ctx->rsize == 0)
781 ctx->rsize = cifs_sb->ctx->rsize;
782 if (ctx->wsize == 0)
783 ctx->wsize = cifs_sb->ctx->wsize;
784
785
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000786 smb3_cleanup_fs_context_contents(cifs_sb->ctx);
787 rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
Ronnie Sahlberg1cb6c3d2020-12-14 16:40:26 +1000788 smb3_update_mnt_flags(cifs_sb);
Paulo Alcantarab6236612021-07-16 03:26:41 -0300789#ifdef CONFIG_CIFS_DFS_UPCALL
790 if (!rc)
791 rc = dfs_cache_remount_fs(cifs_sb);
792#endif
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000793
794 return rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600795}
796
797static int smb3_fs_context_parse_param(struct fs_context *fc,
798 struct fs_parameter *param)
799{
800 struct fs_parse_result result;
801 struct smb3_fs_context *ctx = smb3_fc2context(fc);
802 int i, opt;
803 bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
804 bool skip_parsing = false;
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000805 kuid_t uid;
806 kgid_t gid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600807
808 cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
809
810 /*
811 * fs_parse can not handle string options with an empty value so
812 * we will need special handling of them.
813 */
814 if (param->type == fs_value_is_string && param->string[0] == 0) {
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000815 if (!strcmp("pass", param->key) || !strcmp("password", param->key)) {
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600816 skip_parsing = true;
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000817 opt = Opt_pass;
Steve French31f65512020-12-16 16:26:35 -0600818 } else if (!strcmp("user", param->key) || !strcmp("username", param->key)) {
819 skip_parsing = true;
820 opt = Opt_user;
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000821 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600822 }
823
824 if (!skip_parsing) {
825 opt = fs_parse(fc, smb3_fs_parameters, param, &result);
826 if (opt < 0)
827 return ctx->sloppy ? 1 : opt;
828 }
829
830 switch (opt) {
831 case Opt_compress:
832 ctx->compression = UNKNOWN_TYPE;
833 cifs_dbg(VFS,
834 "SMB3 compression support is experimental\n");
835 break;
836 case Opt_nodfs:
837 ctx->nodfs = 1;
838 break;
839 case Opt_hard:
840 if (result.negated)
841 ctx->retry = 0;
842 else
843 ctx->retry = 1;
844 break;
845 case Opt_soft:
846 if (result.negated)
847 ctx->retry = 1;
848 else
849 ctx->retry = 0;
850 break;
851 case Opt_mapposix:
852 if (result.negated)
853 ctx->remap = false;
854 else {
855 ctx->remap = true;
856 ctx->sfu_remap = false; /* disable SFU mapping */
857 }
858 break;
859 case Opt_user_xattr:
860 if (result.negated)
861 ctx->no_xattr = 1;
862 else
863 ctx->no_xattr = 0;
864 break;
865 case Opt_forceuid:
866 if (result.negated)
867 ctx->override_uid = 0;
868 else
869 ctx->override_uid = 1;
870 break;
871 case Opt_forcegid:
872 if (result.negated)
873 ctx->override_gid = 0;
874 else
875 ctx->override_gid = 1;
876 break;
877 case Opt_perm:
878 if (result.negated)
879 ctx->noperm = 1;
880 else
881 ctx->noperm = 0;
882 break;
883 case Opt_dynperm:
884 if (result.negated)
885 ctx->dynperm = 0;
886 else
887 ctx->dynperm = 1;
888 break;
889 case Opt_sfu:
890 if (result.negated)
891 ctx->sfu_emul = 0;
892 else
893 ctx->sfu_emul = 1;
894 break;
895 case Opt_noblocksend:
896 ctx->noblocksnd = 1;
897 break;
898 case Opt_noautotune:
899 ctx->noautotune = 1;
900 break;
901 case Opt_nolease:
902 ctx->no_lease = 1;
903 break;
904 case Opt_nodelete:
905 ctx->nodelete = 1;
906 break;
907 case Opt_multichannel:
908 if (result.negated) {
909 ctx->multichannel = false;
910 ctx->max_channels = 1;
911 } else {
912 ctx->multichannel = true;
913 /* if number of channels not specified, default to 2 */
914 if (ctx->max_channels < 2)
915 ctx->max_channels = 2;
916 }
917 break;
918 case Opt_uid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000919 uid = make_kuid(current_user_ns(), result.uint_32);
920 if (!uid_valid(uid))
921 goto cifs_parse_mount_err;
922 ctx->linux_uid = uid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600923 ctx->uid_specified = true;
924 break;
925 case Opt_cruid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000926 uid = make_kuid(current_user_ns(), result.uint_32);
927 if (!uid_valid(uid))
928 goto cifs_parse_mount_err;
929 ctx->cred_uid = uid;
930 ctx->cruid_specified = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600931 break;
Ronnie Sahlbergb946dbc2021-07-28 16:38:29 +1000932 case Opt_backupuid:
933 uid = make_kuid(current_user_ns(), result.uint_32);
934 if (!uid_valid(uid))
935 goto cifs_parse_mount_err;
936 ctx->backupuid = uid;
937 ctx->backupuid_specified = true;
938 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600939 case Opt_backupgid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000940 gid = make_kgid(current_user_ns(), result.uint_32);
941 if (!gid_valid(gid))
942 goto cifs_parse_mount_err;
943 ctx->backupgid = gid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600944 ctx->backupgid_specified = true;
945 break;
946 case Opt_gid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000947 gid = make_kgid(current_user_ns(), result.uint_32);
948 if (!gid_valid(gid))
949 goto cifs_parse_mount_err;
950 ctx->linux_gid = gid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600951 ctx->gid_specified = true;
952 break;
953 case Opt_port:
954 ctx->port = result.uint_32;
955 break;
956 case Opt_file_mode:
957 ctx->file_mode = result.uint_32;
958 break;
959 case Opt_dirmode:
960 ctx->dir_mode = result.uint_32;
961 break;
962 case Opt_min_enc_offload:
963 ctx->min_offload = result.uint_32;
964 break;
965 case Opt_blocksize:
966 /*
967 * inode blocksize realistically should never need to be
968 * less than 16K or greater than 16M and default is 1MB.
969 * Note that small inode block sizes (e.g. 64K) can lead
970 * to very poor performance of common tools like cp and scp
971 */
972 if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||
973 (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100974 cifs_errorf(fc, "%s: Invalid blocksize\n",
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600975 __func__);
976 goto cifs_parse_mount_err;
977 }
978 ctx->bsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000979 ctx->got_bsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600980 break;
Steve Frenchb8d64f82021-04-24 21:46:23 -0500981 case Opt_rasize:
982 /*
983 * readahead size realistically should never need to be
984 * less than 1M (CIFS_DEFAULT_IOSIZE) or greater than 32M
985 * (perhaps an exception should be considered in the
986 * for the case of a large number of channels
987 * when multichannel is negotiated) since that would lead
988 * to plenty of parallel I/O in flight to the server.
989 * Note that smaller read ahead sizes would
990 * hurt performance of common tools like cp and scp
991 * which often trigger sequential i/o with read ahead
992 */
993 if ((result.uint_32 > (8 * SMB3_DEFAULT_IOSIZE)) ||
994 (result.uint_32 < CIFS_DEFAULT_IOSIZE)) {
995 cifs_errorf(fc, "%s: Invalid rasize %d vs. %d\n",
996 __func__, result.uint_32, SMB3_DEFAULT_IOSIZE);
997 goto cifs_parse_mount_err;
998 }
999 ctx->rasize = result.uint_32;
1000 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001001 case Opt_rsize:
1002 ctx->rsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +10001003 ctx->got_rsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001004 break;
1005 case Opt_wsize:
1006 ctx->wsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +10001007 ctx->got_wsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001008 break;
Steve French57804642021-02-24 12:12:53 -06001009 case Opt_acregmax:
1010 ctx->acregmax = HZ * result.uint_32;
1011 if (ctx->acregmax > CIFS_MAX_ACTIMEO) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001012 cifs_errorf(fc, "acregmax too large\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001013 goto cifs_parse_mount_err;
1014 }
1015 break;
Steve French4c9f9482021-02-23 15:50:57 -06001016 case Opt_acdirmax:
1017 ctx->acdirmax = HZ * result.uint_32;
1018 if (ctx->acdirmax > CIFS_MAX_ACTIMEO) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001019 cifs_errorf(fc, "acdirmax too large\n");
Steve French4c9f9482021-02-23 15:50:57 -06001020 goto cifs_parse_mount_err;
1021 }
1022 break;
Steve French57804642021-02-24 12:12:53 -06001023 case Opt_actimeo:
1024 if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001025 cifs_errorf(fc, "timeout too large\n");
Steve French57804642021-02-24 12:12:53 -06001026 goto cifs_parse_mount_err;
1027 }
1028 if ((ctx->acdirmax != CIFS_DEF_ACTIMEO) ||
1029 (ctx->acregmax != CIFS_DEF_ACTIMEO)) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001030 cifs_errorf(fc, "actimeo ignored since acregmax or acdirmax specified\n");
Steve French57804642021-02-24 12:12:53 -06001031 break;
1032 }
1033 ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
1034 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001035 case Opt_echo_interval:
1036 ctx->echo_interval = result.uint_32;
1037 break;
1038 case Opt_snapshot:
1039 ctx->snapshot_time = result.uint_32;
1040 break;
1041 case Opt_max_credits:
1042 if (result.uint_32 < 20 || result.uint_32 > 60000) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001043 cifs_errorf(fc, "%s: Invalid max_credits value\n",
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001044 __func__);
1045 goto cifs_parse_mount_err;
1046 }
1047 ctx->max_credits = result.uint_32;
1048 break;
1049 case Opt_max_channels:
1050 if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001051 cifs_errorf(fc, "%s: Invalid max_channels value, needs to be 1-%d\n",
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001052 __func__, CIFS_MAX_CHANNELS);
1053 goto cifs_parse_mount_err;
1054 }
1055 ctx->max_channels = result.uint_32;
Steve Frenchc1f8a392021-05-07 19:33:51 -05001056 /* If more than one channel requested ... they want multichan */
1057 if (result.uint_32 > 1)
1058 ctx->multichannel = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001059 break;
1060 case Opt_handletimeout:
1061 ctx->handle_timeout = result.uint_32;
1062 if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001063 cifs_errorf(fc, "Invalid handle cache timeout, longer than 16 minutes\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001064 goto cifs_parse_mount_err;
1065 }
1066 break;
1067 case Opt_source:
1068 kfree(ctx->UNC);
1069 ctx->UNC = NULL;
1070 switch (smb3_parse_devname(param->string, ctx)) {
1071 case 0:
1072 break;
1073 case -ENOMEM:
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001074 cifs_errorf(fc, "Unable to allocate memory for devname\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001075 goto cifs_parse_mount_err;
1076 case -EINVAL:
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001077 cifs_errorf(fc, "Malformed UNC in devname\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001078 goto cifs_parse_mount_err;
1079 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001080 cifs_errorf(fc, "Unknown error parsing devname\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001081 goto cifs_parse_mount_err;
1082 }
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +10001083 ctx->source = kstrdup(param->string, GFP_KERNEL);
1084 if (ctx->source == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001085 cifs_errorf(fc, "OOM when copying UNC string\n");
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +10001086 goto cifs_parse_mount_err;
1087 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001088 fc->source = kstrdup(param->string, GFP_KERNEL);
1089 if (fc->source == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001090 cifs_errorf(fc, "OOM when copying UNC string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001091 goto cifs_parse_mount_err;
1092 }
1093 break;
1094 case Opt_user:
1095 kfree(ctx->username);
1096 ctx->username = NULL;
1097 if (strlen(param->string) == 0) {
1098 /* null user, ie. anonymous authentication */
1099 ctx->nullauth = 1;
1100 break;
1101 }
1102
1103 if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) >
1104 CIFS_MAX_USERNAME_LEN) {
1105 pr_warn("username too long\n");
1106 goto cifs_parse_mount_err;
1107 }
1108 ctx->username = kstrdup(param->string, GFP_KERNEL);
1109 if (ctx->username == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001110 cifs_errorf(fc, "OOM when copying username string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001111 goto cifs_parse_mount_err;
1112 }
1113 break;
1114 case Opt_pass:
1115 kfree(ctx->password);
1116 ctx->password = NULL;
1117 if (strlen(param->string) == 0)
1118 break;
1119
1120 ctx->password = kstrdup(param->string, GFP_KERNEL);
1121 if (ctx->password == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001122 cifs_errorf(fc, "OOM when copying password string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001123 goto cifs_parse_mount_err;
1124 }
1125 break;
1126 case Opt_ip:
1127 if (strlen(param->string) == 0) {
1128 ctx->got_ip = false;
1129 break;
1130 }
1131 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
1132 param->string,
1133 strlen(param->string))) {
1134 pr_err("bad ip= option (%s)\n", param->string);
1135 goto cifs_parse_mount_err;
1136 }
1137 ctx->got_ip = true;
1138 break;
1139 case Opt_domain:
1140 if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN)
1141 == CIFS_MAX_DOMAINNAME_LEN) {
1142 pr_warn("domain name too long\n");
1143 goto cifs_parse_mount_err;
1144 }
1145
1146 kfree(ctx->domainname);
1147 ctx->domainname = kstrdup(param->string, GFP_KERNEL);
1148 if (ctx->domainname == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001149 cifs_errorf(fc, "OOM when copying domainname string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001150 goto cifs_parse_mount_err;
1151 }
1152 cifs_dbg(FYI, "Domain name set\n");
1153 break;
1154 case Opt_srcaddr:
1155 if (!cifs_convert_address(
1156 (struct sockaddr *)&ctx->srcaddr,
1157 param->string, strlen(param->string))) {
1158 pr_warn("Could not parse srcaddr: %s\n",
1159 param->string);
1160 goto cifs_parse_mount_err;
1161 }
1162 break;
1163 case Opt_iocharset:
1164 if (strnlen(param->string, 1024) >= 65) {
1165 pr_warn("iocharset name too long\n");
1166 goto cifs_parse_mount_err;
1167 }
1168
1169 if (strncasecmp(param->string, "default", 7) != 0) {
1170 kfree(ctx->iocharset);
1171 ctx->iocharset = kstrdup(param->string, GFP_KERNEL);
1172 if (ctx->iocharset == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001173 cifs_errorf(fc, "OOM when copying iocharset string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001174 goto cifs_parse_mount_err;
1175 }
1176 }
1177 /* if iocharset not set then load_nls_default
1178 * is used by caller
1179 */
Jiapeng Chonge83aa352021-05-19 18:47:07 +08001180 cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001181 break;
1182 case Opt_netbiosname:
1183 memset(ctx->source_rfc1001_name, 0x20,
1184 RFC1001_NAME_LEN);
1185 /*
1186 * FIXME: are there cases in which a comma can
1187 * be valid in workstation netbios name (and
1188 * need special handling)?
1189 */
1190 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1191 /* don't ucase netbiosname for user */
1192 if (param->string[i] == 0)
1193 break;
1194 ctx->source_rfc1001_name[i] = param->string[i];
1195 }
1196 /* The string has 16th byte zero still from
1197 * set at top of the function
1198 */
1199 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1200 pr_warn("netbiosname longer than 15 truncated\n");
1201 break;
1202 case Opt_servern:
1203 /* last byte, type, is 0x20 for servr type */
1204 memset(ctx->target_rfc1001_name, 0x20,
1205 RFC1001_NAME_LEN_WITH_NULL);
1206 /*
1207 * BB are there cases in which a comma can be valid in this
1208 * workstation netbios name (and need special handling)?
1209 */
1210
1211 /* user or mount helper must uppercase the netbios name */
1212 for (i = 0; i < 15; i++) {
1213 if (param->string[i] == 0)
1214 break;
1215 ctx->target_rfc1001_name[i] = param->string[i];
1216 }
1217
1218 /* The string has 16th byte zero still from set at top of function */
1219 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1220 pr_warn("server netbiosname longer than 15 truncated\n");
1221 break;
1222 case Opt_ver:
1223 /* version of mount userspace tools, not dialect */
1224 /* If interface changes in mount.cifs bump to new ver */
1225 if (strncasecmp(param->string, "1", 1) == 0) {
1226 if (strlen(param->string) > 1) {
1227 pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
1228 param->string);
1229 goto cifs_parse_mount_err;
1230 }
1231 /* This is the default */
1232 break;
1233 }
1234 /* For all other value, error */
1235 pr_warn("Invalid mount helper version specified\n");
1236 goto cifs_parse_mount_err;
1237 case Opt_vers:
1238 /* protocol version (dialect) */
Aurelien Apteld9a86922021-03-01 19:32:09 +01001239 if (cifs_parse_smb_version(fc, param->string, ctx, is_smb3) != 0)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001240 goto cifs_parse_mount_err;
1241 ctx->got_version = true;
1242 break;
1243 case Opt_sec:
Aurelien Apteld9a86922021-03-01 19:32:09 +01001244 if (cifs_parse_security_flavors(fc, param->string, ctx) != 0)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001245 goto cifs_parse_mount_err;
1246 break;
1247 case Opt_cache:
Aurelien Apteld9a86922021-03-01 19:32:09 +01001248 if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001249 goto cifs_parse_mount_err;
1250 break;
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001251 case Opt_witness:
1252#ifndef CONFIG_CIFS_SWN_UPCALL
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001253 cifs_errorf(fc, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001254 goto cifs_parse_mount_err;
1255#endif
1256 ctx->witness = true;
Steve Frenchdd538032020-12-14 20:15:12 -06001257 pr_warn_once("Witness protocol support is experimental\n");
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001258 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001259 case Opt_rootfs:
Aurelien Aptelaf3ef3b2021-03-18 19:17:10 +01001260#ifndef CONFIG_CIFS_ROOT
1261 cifs_dbg(VFS, "rootfs support requires CONFIG_CIFS_ROOT config option\n");
1262 goto cifs_parse_mount_err;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001263#endif
Aurelien Aptelaf3ef3b2021-03-18 19:17:10 +01001264 ctx->rootfs = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001265 break;
1266 case Opt_posixpaths:
1267 if (result.negated)
1268 ctx->posix_paths = 0;
1269 else
1270 ctx->posix_paths = 1;
1271 break;
1272 case Opt_unix:
Steve French7321be22021-08-23 13:52:12 -05001273 if (result.negated) {
1274 if (ctx->linux_ext == 1)
1275 pr_warn_once("conflicting posix mount options specified\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001276 ctx->linux_ext = 0;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001277 ctx->no_linux_ext = 1;
Steve French7321be22021-08-23 13:52:12 -05001278 } else {
1279 if (ctx->no_linux_ext == 1)
1280 pr_warn_once("conflicting posix mount options specified\n");
1281 ctx->linux_ext = 1;
1282 ctx->no_linux_ext = 0;
1283 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001284 break;
1285 case Opt_nocase:
1286 ctx->nocase = 1;
1287 break;
1288 case Opt_brl:
1289 if (result.negated) {
1290 /*
1291 * turn off mandatory locking in mode
1292 * if remote locking is turned off since the
1293 * local vfs will do advisory
1294 */
1295 if (ctx->file_mode ==
1296 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1297 ctx->file_mode = S_IALLUGO;
1298 ctx->nobrl = 1;
1299 } else
1300 ctx->nobrl = 0;
1301 break;
1302 case Opt_handlecache:
1303 if (result.negated)
1304 ctx->nohandlecache = 1;
1305 else
1306 ctx->nohandlecache = 0;
1307 break;
1308 case Opt_forcemandatorylock:
1309 ctx->mand_lock = 1;
1310 break;
1311 case Opt_setuids:
1312 ctx->setuids = result.negated;
1313 break;
1314 case Opt_intr:
1315 ctx->intr = !result.negated;
1316 break;
1317 case Opt_setuidfromacl:
1318 ctx->setuidfromacl = 1;
1319 break;
1320 case Opt_strictsync:
1321 ctx->nostrictsync = result.negated;
1322 break;
1323 case Opt_serverino:
1324 ctx->server_ino = !result.negated;
1325 break;
1326 case Opt_rwpidforward:
1327 ctx->rwpidforward = 1;
1328 break;
1329 case Opt_modesid:
1330 ctx->mode_ace = 1;
1331 break;
1332 case Opt_cifsacl:
1333 ctx->cifs_acl = !result.negated;
1334 break;
1335 case Opt_acl:
1336 ctx->no_psx_acl = result.negated;
1337 break;
1338 case Opt_locallease:
1339 ctx->local_lease = 1;
1340 break;
1341 case Opt_sign:
1342 ctx->sign = true;
1343 break;
1344 case Opt_ignore_signature:
1345 ctx->sign = true;
1346 ctx->ignore_signature = true;
1347 break;
1348 case Opt_seal:
1349 /* we do not do the following in secFlags because seal
1350 * is a per tree connection (mount) not a per socket
1351 * or per-smb connection option in the protocol
1352 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1353 */
1354 ctx->seal = 1;
1355 break;
1356 case Opt_noac:
1357 pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1358 break;
1359 case Opt_fsc:
1360#ifndef CONFIG_CIFS_FSCACHE
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001361 cifs_errorf(fc, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001362 goto cifs_parse_mount_err;
1363#endif
1364 ctx->fsc = true;
1365 break;
1366 case Opt_mfsymlinks:
1367 ctx->mfsymlinks = true;
1368 break;
1369 case Opt_multiuser:
1370 ctx->multiuser = true;
1371 break;
1372 case Opt_sloppy:
1373 ctx->sloppy = true;
1374 break;
1375 case Opt_nosharesock:
1376 ctx->nosharesock = true;
1377 break;
1378 case Opt_persistent:
1379 if (result.negated) {
Steve French27cf9482020-12-16 01:22:54 -06001380 ctx->nopersistent = true;
1381 if (ctx->persistent) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001382 cifs_errorf(fc, "persistenthandles mount options conflict\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001383 goto cifs_parse_mount_err;
1384 }
1385 } else {
Steve French27cf9482020-12-16 01:22:54 -06001386 ctx->persistent = true;
1387 if ((ctx->nopersistent) || (ctx->resilient)) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001388 cifs_errorf(fc, "persistenthandles mount options conflict\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001389 goto cifs_parse_mount_err;
1390 }
1391 }
1392 break;
1393 case Opt_resilient:
1394 if (result.negated) {
1395 ctx->resilient = false; /* already the default */
1396 } else {
1397 ctx->resilient = true;
1398 if (ctx->persistent) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001399 cifs_errorf(fc, "persistenthandles mount options conflict\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001400 goto cifs_parse_mount_err;
1401 }
1402 }
1403 break;
Steve French7ae5e582021-10-14 15:54:26 -05001404 case Opt_tcp_nodelay:
1405 /* tcp nodelay should not usually be needed since we CORK/UNCORK the socket */
1406 if (result.negated)
1407 ctx->sockopt_tcp_nodelay = false;
1408 else
1409 ctx->sockopt_tcp_nodelay = true;
1410 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001411 case Opt_domainauto:
1412 ctx->domainauto = true;
1413 break;
1414 case Opt_rdma:
1415 ctx->rdma = true;
1416 break;
1417 }
Steve French31f65512020-12-16 16:26:35 -06001418 /* case Opt_ignore: - is ignored as expected ... */
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001419
1420 return 0;
1421
1422 cifs_parse_mount_err:
Steve Frenchbd2f0b42021-01-28 16:43:03 -06001423 return -EINVAL;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001424}
1425
1426int smb3_init_fs_context(struct fs_context *fc)
1427{
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001428 int rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001429 struct smb3_fs_context *ctx;
1430 char *nodename = utsname()->nodename;
1431 int i;
1432
1433 ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001434 if (unlikely(!ctx)) {
1435 rc = -ENOMEM;
1436 goto err_exit;
1437 }
1438
1439 ctx->workstation_name = kstrdup(nodename, GFP_KERNEL);
1440 if (unlikely(!ctx->workstation_name)) {
1441 rc = -ENOMEM;
1442 goto err_exit;
1443 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001444
1445 /*
1446 * does not have to be perfect mapping since field is
1447 * informational, only used for servers that do not support
1448 * port 445 and it can be overridden at mount time
1449 */
1450 memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1451 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
1452 ctx->source_rfc1001_name[i] = toupper(nodename[i]);
1453
1454 ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1455 /*
1456 * null target name indicates to use *SMBSERVR default called name
1457 * if we end up sending RFC1001 session initialize
1458 */
1459 ctx->target_rfc1001_name[0] = 0;
1460 ctx->cred_uid = current_uid();
1461 ctx->linux_uid = current_uid();
1462 ctx->linux_gid = current_gid();
Steve Frenchb8d64f82021-04-24 21:46:23 -05001463 /* By default 4MB read ahead size, 1MB block size */
1464 ctx->bsize = CIFS_DEFAULT_IOSIZE; /* can improve cp performance significantly */
1465 ctx->rasize = 0; /* 0 = use default (ie negotiated rsize) for read ahead pages */
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001466
1467 /*
1468 * default to SFM style remapping of seven reserved characters
1469 * unless user overrides it or we negotiate CIFS POSIX where
1470 * it is unnecessary. Can not simultaneously use more than one mapping
1471 * since then readdir could list files that open could not open
1472 */
1473 ctx->remap = true;
1474
1475 /* default to only allowing write access to owner of the mount */
1476 ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1477
1478 /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1479 /* default is always to request posix paths. */
1480 ctx->posix_paths = 1;
1481 /* default to using server inode numbers where available */
1482 ctx->server_ino = 1;
1483
1484 /* default is to use strict cifs caching semantics */
1485 ctx->strict_io = true;
1486
Steve French57804642021-02-24 12:12:53 -06001487 ctx->acregmax = CIFS_DEF_ACTIMEO;
Steve French4c9f9482021-02-23 15:50:57 -06001488 ctx->acdirmax = CIFS_DEF_ACTIMEO;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001489
1490 /* Most clients set timeout to 0, allows server to use its default */
1491 ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1492
1493 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1494 ctx->ops = &smb30_operations;
1495 ctx->vals = &smbdefault_values;
1496
1497 ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1498
1499 /* default to no multichannel (single server connection) */
1500 ctx->multichannel = false;
1501 ctx->max_channels = 1;
1502
1503 ctx->backupuid_specified = false; /* no backup intent for a user */
1504 ctx->backupgid_specified = false; /* no backup intent for a group */
1505
1506/*
1507 * short int override_uid = -1;
1508 * short int override_gid = -1;
1509 * char *nodename = strdup(utsname()->nodename);
1510 * struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
1511 */
1512
1513 fc->fs_private = ctx;
1514 fc->ops = &smb3_fs_context_ops;
1515 return 0;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001516
1517err_exit:
1518 if (ctx) {
1519 kfree(ctx->workstation_name);
1520 kfree(ctx);
1521 }
1522
1523 return rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001524}
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001525
1526void
1527smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
1528{
1529 if (ctx == NULL)
1530 return;
1531
1532 /*
1533 * Make sure this stays in sync with smb3_fs_context_dup()
1534 */
1535 kfree(ctx->mount_options);
1536 ctx->mount_options = NULL;
1537 kfree(ctx->username);
1538 ctx->username = NULL;
1539 kfree_sensitive(ctx->password);
1540 ctx->password = NULL;
Shyam Prasad N7be32482021-10-14 11:52:39 +00001541 kfree(ctx->server_hostname);
1542 ctx->server_hostname = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001543 kfree(ctx->UNC);
1544 ctx->UNC = NULL;
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +10001545 kfree(ctx->source);
1546 ctx->source = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001547 kfree(ctx->domainname);
1548 ctx->domainname = NULL;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001549 kfree(ctx->workstation_name);
1550 ctx->workstation_name = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001551 kfree(ctx->nodename);
1552 ctx->nodename = NULL;
1553 kfree(ctx->iocharset);
1554 ctx->iocharset = NULL;
1555 kfree(ctx->prepath);
1556 ctx->prepath = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001557}
1558
1559void
1560smb3_cleanup_fs_context(struct smb3_fs_context *ctx)
1561{
1562 if (!ctx)
1563 return;
1564 smb3_cleanup_fs_context_contents(ctx);
1565 kfree(ctx);
1566}
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001567
1568void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
1569{
1570 struct smb3_fs_context *ctx = cifs_sb->ctx;
1571
1572 if (ctx->nodfs)
1573 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
1574 else
1575 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS;
1576
1577 if (ctx->noperm)
1578 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1579 else
1580 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM;
1581
1582 if (ctx->setuids)
1583 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1584 else
1585 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID;
1586
1587 if (ctx->setuidfromacl)
1588 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
1589 else
1590 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL;
1591
1592 if (ctx->server_ino)
1593 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1594 else
1595 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
1596
1597 if (ctx->remap)
1598 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
1599 else
1600 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR;
1601
1602 if (ctx->sfu_remap)
1603 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1604 else
1605 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
1606
1607 if (ctx->no_xattr)
1608 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1609 else
1610 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR;
1611
1612 if (ctx->sfu_emul)
1613 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1614 else
1615 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL;
1616
1617 if (ctx->nobrl)
1618 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1619 else
1620 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL;
1621
1622 if (ctx->nohandlecache)
1623 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
1624 else
1625 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
1626
1627 if (ctx->nostrictsync)
1628 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
1629 else
1630 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC;
1631
1632 if (ctx->mand_lock)
1633 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
1634 else
1635 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL;
1636
1637 if (ctx->rwpidforward)
1638 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
1639 else
1640 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD;
1641
1642 if (ctx->mode_ace)
1643 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
1644 else
1645 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID;
1646
1647 if (ctx->cifs_acl)
1648 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1649 else
1650 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL;
1651
1652 if (ctx->backupuid_specified)
1653 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
1654 else
1655 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
1656
1657 if (ctx->backupgid_specified)
1658 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
1659 else
1660 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
1661
1662 if (ctx->override_uid)
1663 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
1664 else
1665 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID;
1666
1667 if (ctx->override_gid)
1668 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
1669 else
1670 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID;
1671
1672 if (ctx->dynperm)
1673 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
1674 else
1675 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM;
1676
1677 if (ctx->fsc)
1678 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
1679 else
1680 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE;
1681
1682 if (ctx->multiuser)
1683 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
1684 CIFS_MOUNT_NO_PERM);
1685 else
Ronnie Sahlberga0f85e32021-02-10 11:55:47 +10001686 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MULTIUSER;
1687
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001688
1689 if (ctx->strict_io)
1690 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
1691 else
1692 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO;
1693
1694 if (ctx->direct_io)
1695 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1696 else
1697 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO;
1698
1699 if (ctx->mfsymlinks)
1700 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
1701 else
1702 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS;
1703 if (ctx->mfsymlinks) {
1704 if (ctx->sfu_emul) {
1705 /*
1706 * Our SFU ("Services for Unix" emulation does not allow
1707 * creating symlinks but does allow reading existing SFU
1708 * symlinks (it does allow both creating and reading SFU
1709 * style mknod and FIFOs though). When "mfsymlinks" and
1710 * "sfu" are both enabled at the same time, it allows
1711 * reading both types of symlinks, but will only create
1712 * them with mfsymlinks format. This allows better
1713 * Apple compatibility (probably better for Samba too)
1714 * while still recognizing old Windows style symlinks.
1715 */
1716 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
1717 }
1718 }
Steve French087f7572021-04-29 00:18:43 -05001719 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SHUTDOWN;
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001720
1721 return;
1722}