blob: 7ec35f3f0a5fcb20d874e616b2bbf75dc8322d56 [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 Sahlberg5455b9e2022-01-18 12:16:57 +100040static DEFINE_MUTEX(cifs_mount_mutex);
41
Ronnie Sahlberg555782a2020-10-21 12:10:44 +100042static const match_table_t cifs_smb_version_tokens = {
43 { Smb_1, SMB1_VERSION_STRING },
44 { Smb_20, SMB20_VERSION_STRING},
45 { Smb_21, SMB21_VERSION_STRING },
46 { Smb_30, SMB30_VERSION_STRING },
47 { Smb_302, SMB302_VERSION_STRING },
48 { Smb_302, ALT_SMB302_VERSION_STRING },
49 { Smb_311, SMB311_VERSION_STRING },
50 { Smb_311, ALT_SMB311_VERSION_STRING },
51 { Smb_3any, SMB3ANY_VERSION_STRING },
52 { Smb_default, SMBDEFAULT_VERSION_STRING },
53 { Smb_version_err, NULL }
54};
55
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100056static const match_table_t cifs_secflavor_tokens = {
57 { Opt_sec_krb5, "krb5" },
58 { Opt_sec_krb5i, "krb5i" },
59 { Opt_sec_krb5p, "krb5p" },
60 { Opt_sec_ntlmsspi, "ntlmsspi" },
61 { Opt_sec_ntlmssp, "ntlmssp" },
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100062 { Opt_sec_ntlmv2, "nontlm" },
63 { Opt_sec_ntlmv2, "ntlmv2" },
64 { Opt_sec_ntlmv2i, "ntlmv2i" },
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +100065 { Opt_sec_none, "none" },
66
67 { Opt_sec_err, NULL }
68};
69
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -060070const struct fs_parameter_spec smb3_fs_parameters[] = {
71 /* Mount options that take no arguments */
72 fsparam_flag_no("user_xattr", Opt_user_xattr),
73 fsparam_flag_no("forceuid", Opt_forceuid),
74 fsparam_flag_no("multichannel", Opt_multichannel),
75 fsparam_flag_no("forcegid", Opt_forcegid),
76 fsparam_flag("noblocksend", Opt_noblocksend),
77 fsparam_flag("noautotune", Opt_noautotune),
78 fsparam_flag("nolease", Opt_nolease),
79 fsparam_flag_no("hard", Opt_hard),
80 fsparam_flag_no("soft", Opt_soft),
81 fsparam_flag_no("perm", Opt_perm),
82 fsparam_flag("nodelete", Opt_nodelete),
83 fsparam_flag_no("mapposix", Opt_mapposix),
84 fsparam_flag("mapchars", Opt_mapchars),
85 fsparam_flag("nomapchars", Opt_nomapchars),
86 fsparam_flag_no("sfu", Opt_sfu),
87 fsparam_flag("nodfs", Opt_nodfs),
88 fsparam_flag_no("posixpaths", Opt_posixpaths),
89 fsparam_flag_no("unix", Opt_unix),
90 fsparam_flag_no("linux", Opt_unix),
91 fsparam_flag_no("posix", Opt_unix),
92 fsparam_flag("nocase", Opt_nocase),
93 fsparam_flag("ignorecase", Opt_nocase),
94 fsparam_flag_no("brl", Opt_brl),
95 fsparam_flag_no("handlecache", Opt_handlecache),
96 fsparam_flag("forcemandatorylock", Opt_forcemandatorylock),
97 fsparam_flag("forcemand", Opt_forcemandatorylock),
98 fsparam_flag("setuidfromacl", Opt_setuidfromacl),
Steve French27cf9482020-12-16 01:22:54 -060099 fsparam_flag("idsfromsid", Opt_setuidfromacl),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600100 fsparam_flag_no("setuids", Opt_setuids),
101 fsparam_flag_no("dynperm", Opt_dynperm),
102 fsparam_flag_no("intr", Opt_intr),
103 fsparam_flag_no("strictsync", Opt_strictsync),
104 fsparam_flag_no("serverino", Opt_serverino),
105 fsparam_flag("rwpidforward", Opt_rwpidforward),
106 fsparam_flag("cifsacl", Opt_cifsacl),
107 fsparam_flag_no("acl", Opt_acl),
108 fsparam_flag("locallease", Opt_locallease),
109 fsparam_flag("sign", Opt_sign),
110 fsparam_flag("ignore_signature", Opt_ignore_signature),
Steve French27cf9482020-12-16 01:22:54 -0600111 fsparam_flag("signloosely", Opt_ignore_signature),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600112 fsparam_flag("seal", Opt_seal),
113 fsparam_flag("noac", Opt_noac),
114 fsparam_flag("fsc", Opt_fsc),
115 fsparam_flag("mfsymlinks", Opt_mfsymlinks),
116 fsparam_flag("multiuser", Opt_multiuser),
117 fsparam_flag("sloppy", Opt_sloppy),
118 fsparam_flag("nosharesock", Opt_nosharesock),
Steve French27cf9482020-12-16 01:22:54 -0600119 fsparam_flag_no("persistenthandles", Opt_persistent),
120 fsparam_flag_no("resilienthandles", Opt_resilient),
Steve French7ae5e582021-10-14 15:54:26 -0500121 fsparam_flag_no("tcpnodelay", Opt_tcp_nodelay),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600122 fsparam_flag("domainauto", Opt_domainauto),
123 fsparam_flag("rdma", Opt_rdma),
124 fsparam_flag("modesid", Opt_modesid),
Steve French27cf9482020-12-16 01:22:54 -0600125 fsparam_flag("modefromsid", Opt_modesid),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600126 fsparam_flag("rootfs", Opt_rootfs),
127 fsparam_flag("compress", Opt_compress),
Samuel Cabrero0ac4e292020-12-11 22:59:29 -0600128 fsparam_flag("witness", Opt_witness),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600129
130 /* Mount options which take numeric value */
131 fsparam_u32("backupuid", Opt_backupuid),
132 fsparam_u32("backupgid", Opt_backupgid),
133 fsparam_u32("uid", Opt_uid),
134 fsparam_u32("cruid", Opt_cruid),
135 fsparam_u32("gid", Opt_gid),
136 fsparam_u32("file_mode", Opt_file_mode),
137 fsparam_u32("dirmode", Opt_dirmode),
138 fsparam_u32("dir_mode", Opt_dirmode),
139 fsparam_u32("port", Opt_port),
140 fsparam_u32("min_enc_offload", Opt_min_enc_offload),
Steve French27cf9482020-12-16 01:22:54 -0600141 fsparam_u32("esize", Opt_min_enc_offload),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600142 fsparam_u32("bsize", Opt_blocksize),
Steve Frenchb8d64f82021-04-24 21:46:23 -0500143 fsparam_u32("rasize", Opt_rasize),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600144 fsparam_u32("rsize", Opt_rsize),
145 fsparam_u32("wsize", Opt_wsize),
146 fsparam_u32("actimeo", Opt_actimeo),
Steve French4c9f9482021-02-23 15:50:57 -0600147 fsparam_u32("acdirmax", Opt_acdirmax),
Steve French57804642021-02-24 12:12:53 -0600148 fsparam_u32("acregmax", Opt_acregmax),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600149 fsparam_u32("echo_interval", Opt_echo_interval),
150 fsparam_u32("max_credits", Opt_max_credits),
151 fsparam_u32("handletimeout", Opt_handletimeout),
152 fsparam_u32("snapshot", Opt_snapshot),
153 fsparam_u32("max_channels", Opt_max_channels),
154
155 /* Mount options which take string value */
156 fsparam_string("source", Opt_source),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600157 fsparam_string("user", Opt_user),
158 fsparam_string("username", Opt_user),
159 fsparam_string("pass", Opt_pass),
160 fsparam_string("password", Opt_pass),
161 fsparam_string("ip", Opt_ip),
162 fsparam_string("addr", Opt_ip),
163 fsparam_string("domain", Opt_domain),
164 fsparam_string("dom", Opt_domain),
165 fsparam_string("srcaddr", Opt_srcaddr),
166 fsparam_string("iocharset", Opt_iocharset),
167 fsparam_string("netbiosname", Opt_netbiosname),
168 fsparam_string("servern", Opt_servern),
169 fsparam_string("ver", Opt_ver),
170 fsparam_string("vers", Opt_vers),
171 fsparam_string("sec", Opt_sec),
172 fsparam_string("cache", Opt_cache),
173
174 /* Arguments that should be ignored */
175 fsparam_flag("guest", Opt_ignore),
176 fsparam_flag("noatime", Opt_ignore),
177 fsparam_flag("relatime", Opt_ignore),
178 fsparam_flag("_netdev", Opt_ignore),
179 fsparam_flag_no("suid", Opt_ignore),
180 fsparam_flag_no("exec", Opt_ignore),
181 fsparam_flag_no("dev", Opt_ignore),
182 fsparam_flag_no("mand", Opt_ignore),
Adam Harvey19d51582021-01-27 13:44:35 -0800183 fsparam_flag_no("auto", Opt_ignore),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600184 fsparam_string("cred", Opt_ignore),
185 fsparam_string("credentials", Opt_ignore),
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000186 /*
187 * UNC and prefixpath is now extracted from Opt_source
188 * in the new mount API so we can just ignore them going forward.
189 */
190 fsparam_string("unc", Opt_ignore),
Steve Frenchc9b8cd62021-01-28 11:20:22 -0600191 fsparam_string("prefixpath", Opt_ignore),
Dmitry Osipenko427c4f02020-12-14 14:37:45 +0300192 {}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600193};
194
Aurelien Apteld9a86922021-03-01 19:32:09 +0100195static int
196cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000197{
198
199 substring_t args[MAX_OPT_ARGS];
200
201 /*
202 * With mount options, the last one should win. Reset any existing
203 * settings back to default.
204 */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600205 ctx->sectype = Unspecified;
206 ctx->sign = false;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000207
208 switch (match_token(value, cifs_secflavor_tokens, args)) {
209 case Opt_sec_krb5p:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100210 cifs_errorf(fc, "sec=krb5p is not supported!\n");
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000211 return 1;
212 case Opt_sec_krb5i:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600213 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000214 fallthrough;
215 case Opt_sec_krb5:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600216 ctx->sectype = Kerberos;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000217 break;
218 case Opt_sec_ntlmsspi:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600219 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000220 fallthrough;
221 case Opt_sec_ntlmssp:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600222 ctx->sectype = RawNTLMSSP;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000223 break;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000224 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;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000230 case Opt_sec_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600231 ctx->nullauth = 1;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000232 break;
233 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100234 cifs_errorf(fc, "bad security option: %s\n", value);
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000235 return 1;
236 }
237
238 return 0;
239}
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000240
241static const match_table_t cifs_cacheflavor_tokens = {
242 { Opt_cache_loose, "loose" },
243 { Opt_cache_strict, "strict" },
244 { Opt_cache_none, "none" },
245 { Opt_cache_ro, "ro" },
246 { Opt_cache_rw, "singleclient" },
247 { Opt_cache_err, NULL }
248};
249
Aurelien Apteld9a86922021-03-01 19:32:09 +0100250static int
251cifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000252{
253 substring_t args[MAX_OPT_ARGS];
254
255 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
256 case Opt_cache_loose:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600257 ctx->direct_io = false;
258 ctx->strict_io = false;
259 ctx->cache_ro = false;
260 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000261 break;
262 case Opt_cache_strict:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600263 ctx->direct_io = false;
264 ctx->strict_io = true;
265 ctx->cache_ro = false;
266 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000267 break;
268 case Opt_cache_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600269 ctx->direct_io = true;
270 ctx->strict_io = false;
271 ctx->cache_ro = false;
272 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000273 break;
274 case Opt_cache_ro:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600275 ctx->direct_io = false;
276 ctx->strict_io = false;
277 ctx->cache_ro = true;
278 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000279 break;
280 case Opt_cache_rw:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600281 ctx->direct_io = false;
282 ctx->strict_io = false;
283 ctx->cache_ro = false;
284 ctx->cache_rw = true;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000285 break;
286 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100287 cifs_errorf(fc, "bad cache= option: %s\n", value);
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000288 return 1;
289 }
290 return 0;
291}
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000292
293#define DUP_CTX_STR(field) \
294do { \
295 if (ctx->field) { \
296 new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC); \
297 if (new_ctx->field == NULL) { \
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000298 smb3_cleanup_fs_context_contents(new_ctx); \
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000299 return -ENOMEM; \
300 } \
301 } \
302} while (0)
303
304int
305smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)
306{
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000307 memcpy(new_ctx, ctx, sizeof(*ctx));
308 new_ctx->prepath = NULL;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600309 new_ctx->mount_options = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000310 new_ctx->nodename = NULL;
311 new_ctx->username = NULL;
312 new_ctx->password = NULL;
Paulo Alcantara869da642021-11-12 14:53:36 -0300313 new_ctx->server_hostname = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000314 new_ctx->domainname = NULL;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000315 new_ctx->workstation_name = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000316 new_ctx->UNC = NULL;
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000317 new_ctx->source = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000318 new_ctx->iocharset = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000319 /*
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000320 * Make sure to stay in sync with smb3_cleanup_fs_context_contents()
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000321 */
322 DUP_CTX_STR(prepath);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600323 DUP_CTX_STR(mount_options);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000324 DUP_CTX_STR(username);
325 DUP_CTX_STR(password);
Shyam Prasad N7be32482021-10-14 11:52:39 +0000326 DUP_CTX_STR(server_hostname);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000327 DUP_CTX_STR(UNC);
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000328 DUP_CTX_STR(source);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000329 DUP_CTX_STR(domainname);
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000330 DUP_CTX_STR(workstation_name);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000331 DUP_CTX_STR(nodename);
332 DUP_CTX_STR(iocharset);
333
Menglong Dongc13e7af2021-01-12 01:13:40 -0800334 return 0;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000335}
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000336
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600337static int
Aurelien Apteld9a86922021-03-01 19:32:09 +0100338cifs_parse_smb_version(struct fs_context *fc, char *value, struct smb3_fs_context *ctx, bool is_smb3)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600339{
340 substring_t args[MAX_OPT_ARGS];
341
342 switch (match_token(value, cifs_smb_version_tokens, args)) {
343#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
344 case Smb_1:
345 if (disable_legacy_dialects) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100346 cifs_errorf(fc, "mount with legacy dialect disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600347 return 1;
348 }
349 if (is_smb3) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100350 cifs_errorf(fc, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600351 return 1;
352 }
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100353 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 -0600354 ctx->ops = &smb1_operations;
355 ctx->vals = &smb1_values;
356 break;
357 case Smb_20:
358 if (disable_legacy_dialects) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100359 cifs_errorf(fc, "mount with legacy dialect disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600360 return 1;
361 }
362 if (is_smb3) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100363 cifs_errorf(fc, "vers=2.0 not permitted when mounting with smb3\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600364 return 1;
365 }
366 ctx->ops = &smb20_operations;
367 ctx->vals = &smb20_values;
368 break;
369#else
370 case Smb_1:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100371 cifs_errorf(fc, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600372 return 1;
373 case Smb_20:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100374 cifs_errorf(fc, "vers=2.0 mount not permitted when legacy dialects disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600375 return 1;
376#endif /* CIFS_ALLOW_INSECURE_LEGACY */
377 case Smb_21:
378 ctx->ops = &smb21_operations;
379 ctx->vals = &smb21_values;
380 break;
381 case Smb_30:
382 ctx->ops = &smb30_operations;
383 ctx->vals = &smb30_values;
384 break;
385 case Smb_302:
386 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
387 ctx->vals = &smb302_values;
388 break;
389 case Smb_311:
390 ctx->ops = &smb311_operations;
391 ctx->vals = &smb311_values;
392 break;
393 case Smb_3any:
394 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
395 ctx->vals = &smb3any_values;
396 break;
397 case Smb_default:
Steve French6dffa4c2021-02-02 00:03:58 -0600398 ctx->ops = &smb30_operations;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600399 ctx->vals = &smbdefault_values;
400 break;
401 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100402 cifs_errorf(fc, "Unknown vers= option specified: %s\n", value);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600403 return 1;
404 }
405 return 0;
406}
407
Ronnie Sahlberg0d4873f2021-01-28 21:35:10 -0600408int smb3_parse_opt(const char *options, const char *key, char **val)
409{
410 int rc = -ENOENT;
411 char *opts, *orig, *p;
412
413 orig = opts = kstrdup(options, GFP_KERNEL);
414 if (!opts)
415 return -ENOMEM;
416
417 while ((p = strsep(&opts, ","))) {
418 char *nval;
419
420 if (!*p)
421 continue;
422 if (strncasecmp(p, key, strlen(key)))
423 continue;
424 nval = strchr(p, '=');
425 if (nval) {
426 if (nval == p)
427 continue;
428 *nval++ = 0;
Al Viro8d767222021-03-05 15:02:34 -0500429 *val = kstrdup(nval, GFP_KERNEL);
Ronnie Sahlberg0d4873f2021-01-28 21:35:10 -0600430 rc = !*val ? -ENOMEM : 0;
431 goto out;
432 }
433 }
434out:
435 kfree(orig);
436 return rc;
437}
438
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000439/*
Thiago Rafael Beckera3108082021-12-17 15:20:22 -0300440 * Remove duplicate path delimiters. Windows is supposed to do that
441 * but there are some bugs that prevent rename from working if there are
442 * multiple delimiters.
443 *
444 * Returns a sanitized duplicate of @path. The caller is responsible for
445 * cleaning up the original.
446 */
447#define IS_DELIM(c) ((c) == '/' || (c) == '\\')
448static char *sanitize_path(char *path)
449{
450 char *cursor1 = path, *cursor2 = path;
451
452 /* skip all prepended delimiters */
453 while (IS_DELIM(*cursor1))
454 cursor1++;
455
456 /* copy the first letter */
457 *cursor2 = *cursor1;
458
459 /* copy the remainder... */
460 while (*(cursor1++)) {
461 /* ... skipping all duplicated delimiters */
462 if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2))
463 continue;
464 *(++cursor2) = *cursor1;
465 }
466
467 /* if the last character is a delimiter, skip it */
468 if (IS_DELIM(*(cursor2 - 1)))
469 cursor2--;
470
471 *(cursor2) = '\0';
472 return kstrdup(path, GFP_KERNEL);
473}
474
475/*
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000476 * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath
477 * fields with the result. Returns 0 on success and an error otherwise
478 * (e.g. ENOMEM or EINVAL)
479 */
480int
481smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
482{
483 char *pos;
484 const char *delims = "/\\";
485 size_t len;
486
487 if (unlikely(!devname || !*devname)) {
488 cifs_dbg(VFS, "Device name not specified\n");
489 return -EINVAL;
490 }
491
492 /* make sure we have a valid UNC double delimiter prefix */
493 len = strspn(devname, delims);
494 if (len != 2)
495 return -EINVAL;
496
497 /* find delimiter between host and sharename */
498 pos = strpbrk(devname + 2, delims);
499 if (!pos)
500 return -EINVAL;
501
Shyam Prasad N7be32482021-10-14 11:52:39 +0000502 /* record the server hostname */
Paulo Alcantara869da642021-11-12 14:53:36 -0300503 kfree(ctx->server_hostname);
Shyam Prasad N7be32482021-10-14 11:52:39 +0000504 ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL);
505 if (!ctx->server_hostname)
506 return -ENOMEM;
507
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000508 /* skip past delimiter */
509 ++pos;
510
511 /* now go until next delimiter or end of string */
512 len = strcspn(pos, delims);
513
514 /* move "pos" up to delimiter or NULL */
515 pos += len;
Paulo Alcantara5c1acf32021-05-03 11:55:26 -0300516 kfree(ctx->UNC);
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000517 ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
518 if (!ctx->UNC)
519 return -ENOMEM;
520
521 convert_delimiter(ctx->UNC, '\\');
522
523 /* skip any delimiter */
524 if (*pos == '/' || *pos == '\\')
525 pos++;
526
Paulo Alcantara5c1acf32021-05-03 11:55:26 -0300527 kfree(ctx->prepath);
528 ctx->prepath = NULL;
529
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000530 /* If pos is NULL then no prepath */
531 if (!*pos)
532 return 0;
533
Thiago Rafael Beckera3108082021-12-17 15:20:22 -0300534 ctx->prepath = sanitize_path(pos);
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000535 if (!ctx->prepath)
536 return -ENOMEM;
537
538 return 0;
539}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600540
541static void smb3_fs_context_free(struct fs_context *fc);
542static int smb3_fs_context_parse_param(struct fs_context *fc,
543 struct fs_parameter *param);
544static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
545 void *data);
546static int smb3_get_tree(struct fs_context *fc);
547static int smb3_reconfigure(struct fs_context *fc);
548
549static const struct fs_context_operations smb3_fs_context_ops = {
550 .free = smb3_fs_context_free,
551 .parse_param = smb3_fs_context_parse_param,
552 .parse_monolithic = smb3_fs_context_parse_monolithic,
553 .get_tree = smb3_get_tree,
554 .reconfigure = smb3_reconfigure,
555};
556
557/*
558 * Parse a monolithic block of data from sys_mount().
559 * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data
560 * @ctx: The superblock configuration to fill in.
561 * @data: The data to parse
562 *
563 * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be
564 * called from the ->monolithic_mount_data() fs_context operation.
565 *
566 * Returns 0 on success or the error returned by the ->parse_option() fs_context
567 * operation on failure.
568 */
569static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
570 void *data)
571{
572 struct smb3_fs_context *ctx = smb3_fc2context(fc);
573 char *options = data, *key;
574 int ret = 0;
575
576 if (!options)
577 return 0;
578
579 ctx->mount_options = kstrdup(data, GFP_KERNEL);
580 if (ctx->mount_options == NULL)
581 return -ENOMEM;
582
583 ret = security_sb_eat_lsm_opts(options, &fc->security);
584 if (ret)
585 return ret;
586
587 /* BB Need to add support for sep= here TBD */
588 while ((key = strsep(&options, ",")) != NULL) {
Ronnie Sahlbergd08395a2021-02-25 17:36:27 +1000589 size_t len;
590 char *value;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600591
Ronnie Sahlbergd08395a2021-02-25 17:36:27 +1000592 if (*key == 0)
593 break;
594
595 /* Check if following character is the deliminator If yes,
596 * we have encountered a double deliminator reset the NULL
597 * character to the deliminator
598 */
599 while (options && options[0] == ',') {
600 len = strlen(key);
601 strcpy(key + len, options);
602 options = strchr(options, ',');
603 if (options)
604 *options++ = 0;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600605 }
Ronnie Sahlbergd08395a2021-02-25 17:36:27 +1000606
607
608 len = 0;
609 value = strchr(key, '=');
610 if (value) {
611 if (value == key)
612 continue;
613 *value++ = 0;
614 len = strlen(value);
615 }
616
617 ret = vfs_parse_fs_string(fc, key, value, len);
618 if (ret < 0)
619 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600620 }
621
622 return ret;
623}
624
625/*
626 * Validate the preparsed information in the config.
627 */
628static int smb3_fs_context_validate(struct fs_context *fc)
629{
630 struct smb3_fs_context *ctx = smb3_fc2context(fc);
631
632 if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100633 cifs_errorf(fc, "SMB Direct requires Version >=3.0\n");
Steve Frenchbd2f0b42021-01-28 16:43:03 -0600634 return -EOPNOTSUPP;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600635 }
636
637#ifndef CONFIG_KEYS
638 /* Muliuser mounts require CONFIG_KEYS support */
639 if (ctx->multiuser) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100640 cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600641 return -1;
642 }
643#endif
644
645 if (ctx->got_version == false)
646 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");
647
648
649 if (!ctx->UNC) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100650 cifs_errorf(fc, "CIFS mount error: No usable UNC path provided in device string!\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600651 return -1;
652 }
653
654 /* make sure UNC has a share name */
655 if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100656 cifs_errorf(fc, "Malformed UNC. Unable to find share name.\n");
Steve Frenchbd2f0b42021-01-28 16:43:03 -0600657 return -ENOENT;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600658 }
659
660 if (!ctx->got_ip) {
661 int len;
662 const char *slash;
663
664 /* No ip= option specified? Try to get it from UNC */
665 /* Use the address part of the UNC. */
666 slash = strchr(&ctx->UNC[2], '\\');
667 len = slash - &ctx->UNC[2];
668 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
669 &ctx->UNC[2], len)) {
670 pr_err("Unable to determine destination address\n");
Steve Frenchbd2f0b42021-01-28 16:43:03 -0600671 return -EHOSTUNREACH;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600672 }
673 }
674
675 /* set the port that we got earlier */
676 cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
677
678 if (ctx->override_uid && !ctx->uid_specified) {
679 ctx->override_uid = 0;
680 pr_notice("ignoring forceuid mount option specified with no uid= option\n");
681 }
682
683 if (ctx->override_gid && !ctx->gid_specified) {
684 ctx->override_gid = 0;
685 pr_notice("ignoring forcegid mount option specified with no gid= option\n");
686 }
687
688 return 0;
689}
690
691static int smb3_get_tree_common(struct fs_context *fc)
692{
693 struct smb3_fs_context *ctx = smb3_fc2context(fc);
694 struct dentry *root;
695 int rc = 0;
696
697 root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);
698 if (IS_ERR(root))
699 return PTR_ERR(root);
700
701 fc->root = root;
702
703 return rc;
704}
705
706/*
707 * Create an SMB3 superblock from the parameters passed.
708 */
709static int smb3_get_tree(struct fs_context *fc)
710{
711 int err = smb3_fs_context_validate(fc);
Ronnie Sahlberg5455b9e2022-01-18 12:16:57 +1000712 int ret;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600713
714 if (err)
715 return err;
Ronnie Sahlberg5455b9e2022-01-18 12:16:57 +1000716 mutex_lock(&cifs_mount_mutex);
717 ret = smb3_get_tree_common(fc);
718 mutex_unlock(&cifs_mount_mutex);
719 return ret;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600720}
721
722static void smb3_fs_context_free(struct fs_context *fc)
723{
724 struct smb3_fs_context *ctx = smb3_fc2context(fc);
725
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000726 smb3_cleanup_fs_context(ctx);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600727}
728
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000729/*
730 * Compare the old and new proposed context during reconfigure
731 * and check if the changes are compatible.
732 */
Aurelien Apteld9a86922021-03-01 19:32:09 +0100733static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
734 struct smb3_fs_context *new_ctx,
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000735 struct smb3_fs_context *old_ctx)
736{
Ronnie Sahlberg531f03b2020-12-14 16:40:23 +1000737 if (new_ctx->posix_paths != old_ctx->posix_paths) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100738 cifs_errorf(fc, "can not change posixpaths during remount\n");
Ronnie Sahlberg531f03b2020-12-14 16:40:23 +1000739 return -EINVAL;
740 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000741 if (new_ctx->sectype != old_ctx->sectype) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100742 cifs_errorf(fc, "can not change sec during remount\n");
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000743 return -EINVAL;
744 }
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000745 if (new_ctx->multiuser != old_ctx->multiuser) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100746 cifs_errorf(fc, "can not change multiuser during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000747 return -EINVAL;
748 }
749 if (new_ctx->UNC &&
750 (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100751 cifs_errorf(fc, "can not change UNC during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000752 return -EINVAL;
753 }
754 if (new_ctx->username &&
755 (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100756 cifs_errorf(fc, "can not change username during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000757 return -EINVAL;
758 }
759 if (new_ctx->password &&
760 (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100761 cifs_errorf(fc, "can not change password during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000762 return -EINVAL;
763 }
764 if (new_ctx->domainname &&
765 (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100766 cifs_errorf(fc, "can not change domainname during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000767 return -EINVAL;
768 }
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000769 if (new_ctx->workstation_name &&
770 (!old_ctx->workstation_name || strcmp(new_ctx->workstation_name, old_ctx->workstation_name))) {
771 cifs_errorf(fc, "can not change workstation_name during remount\n");
772 return -EINVAL;
773 }
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000774 if (new_ctx->nodename &&
775 (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100776 cifs_errorf(fc, "can not change nodename during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000777 return -EINVAL;
778 }
779 if (new_ctx->iocharset &&
780 (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100781 cifs_errorf(fc, "can not change iocharset during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000782 return -EINVAL;
783 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000784
785 return 0;
786}
787
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000788#define STEAL_STRING(cifs_sb, ctx, field) \
789do { \
790 kfree(ctx->field); \
791 ctx->field = cifs_sb->ctx->field; \
792 cifs_sb->ctx->field = NULL; \
793} while (0)
794
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600795static int smb3_reconfigure(struct fs_context *fc)
796{
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000797 struct smb3_fs_context *ctx = smb3_fc2context(fc);
798 struct dentry *root = fc->root;
799 struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
800 int rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600801
Aurelien Apteld9a86922021-03-01 19:32:09 +0100802 rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000803 if (rc)
804 return rc;
805
806 /*
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000807 * We can not change UNC/username/password/domainname/
808 * workstation_name/nodename/iocharset
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000809 * during reconnect so ignore what we have in the new context and
810 * just use what we already have in cifs_sb->ctx.
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000811 */
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000812 STEAL_STRING(cifs_sb, ctx, UNC);
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000813 STEAL_STRING(cifs_sb, ctx, source);
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000814 STEAL_STRING(cifs_sb, ctx, username);
815 STEAL_STRING(cifs_sb, ctx, password);
816 STEAL_STRING(cifs_sb, ctx, domainname);
Shyam Prasad N49bd49f2021-11-05 19:03:57 +0000817 STEAL_STRING(cifs_sb, ctx, workstation_name);
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000818 STEAL_STRING(cifs_sb, ctx, nodename);
819 STEAL_STRING(cifs_sb, ctx, iocharset);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000820
Steve French2d060492020-12-16 18:04:27 -0600821 /* if rsize or wsize not passed in on remount, use previous values */
822 if (ctx->rsize == 0)
823 ctx->rsize = cifs_sb->ctx->rsize;
824 if (ctx->wsize == 0)
825 ctx->wsize = cifs_sb->ctx->wsize;
826
827
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000828 smb3_cleanup_fs_context_contents(cifs_sb->ctx);
829 rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
Ronnie Sahlberg1cb6c3d2020-12-14 16:40:26 +1000830 smb3_update_mnt_flags(cifs_sb);
Paulo Alcantarab6236612021-07-16 03:26:41 -0300831#ifdef CONFIG_CIFS_DFS_UPCALL
832 if (!rc)
833 rc = dfs_cache_remount_fs(cifs_sb);
834#endif
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000835
836 return rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600837}
838
839static int smb3_fs_context_parse_param(struct fs_context *fc,
840 struct fs_parameter *param)
841{
842 struct fs_parse_result result;
843 struct smb3_fs_context *ctx = smb3_fc2context(fc);
844 int i, opt;
845 bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
846 bool skip_parsing = false;
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000847 kuid_t uid;
848 kgid_t gid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600849
850 cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
851
852 /*
853 * fs_parse can not handle string options with an empty value so
854 * we will need special handling of them.
855 */
856 if (param->type == fs_value_is_string && param->string[0] == 0) {
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000857 if (!strcmp("pass", param->key) || !strcmp("password", param->key)) {
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600858 skip_parsing = true;
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000859 opt = Opt_pass;
Steve French31f65512020-12-16 16:26:35 -0600860 } else if (!strcmp("user", param->key) || !strcmp("username", param->key)) {
861 skip_parsing = true;
862 opt = Opt_user;
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000863 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600864 }
865
866 if (!skip_parsing) {
867 opt = fs_parse(fc, smb3_fs_parameters, param, &result);
868 if (opt < 0)
869 return ctx->sloppy ? 1 : opt;
870 }
871
872 switch (opt) {
873 case Opt_compress:
874 ctx->compression = UNKNOWN_TYPE;
875 cifs_dbg(VFS,
876 "SMB3 compression support is experimental\n");
877 break;
878 case Opt_nodfs:
879 ctx->nodfs = 1;
880 break;
881 case Opt_hard:
882 if (result.negated)
883 ctx->retry = 0;
884 else
885 ctx->retry = 1;
886 break;
887 case Opt_soft:
888 if (result.negated)
889 ctx->retry = 1;
890 else
891 ctx->retry = 0;
892 break;
893 case Opt_mapposix:
894 if (result.negated)
895 ctx->remap = false;
896 else {
897 ctx->remap = true;
898 ctx->sfu_remap = false; /* disable SFU mapping */
899 }
900 break;
901 case Opt_user_xattr:
902 if (result.negated)
903 ctx->no_xattr = 1;
904 else
905 ctx->no_xattr = 0;
906 break;
907 case Opt_forceuid:
908 if (result.negated)
909 ctx->override_uid = 0;
910 else
911 ctx->override_uid = 1;
912 break;
913 case Opt_forcegid:
914 if (result.negated)
915 ctx->override_gid = 0;
916 else
917 ctx->override_gid = 1;
918 break;
919 case Opt_perm:
920 if (result.negated)
921 ctx->noperm = 1;
922 else
923 ctx->noperm = 0;
924 break;
925 case Opt_dynperm:
926 if (result.negated)
927 ctx->dynperm = 0;
928 else
929 ctx->dynperm = 1;
930 break;
931 case Opt_sfu:
932 if (result.negated)
933 ctx->sfu_emul = 0;
934 else
935 ctx->sfu_emul = 1;
936 break;
937 case Opt_noblocksend:
938 ctx->noblocksnd = 1;
939 break;
940 case Opt_noautotune:
941 ctx->noautotune = 1;
942 break;
943 case Opt_nolease:
944 ctx->no_lease = 1;
945 break;
946 case Opt_nodelete:
947 ctx->nodelete = 1;
948 break;
949 case Opt_multichannel:
950 if (result.negated) {
951 ctx->multichannel = false;
952 ctx->max_channels = 1;
953 } else {
954 ctx->multichannel = true;
955 /* if number of channels not specified, default to 2 */
956 if (ctx->max_channels < 2)
957 ctx->max_channels = 2;
958 }
959 break;
960 case Opt_uid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000961 uid = make_kuid(current_user_ns(), result.uint_32);
962 if (!uid_valid(uid))
963 goto cifs_parse_mount_err;
964 ctx->linux_uid = uid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600965 ctx->uid_specified = true;
966 break;
967 case Opt_cruid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000968 uid = make_kuid(current_user_ns(), result.uint_32);
969 if (!uid_valid(uid))
970 goto cifs_parse_mount_err;
971 ctx->cred_uid = uid;
972 ctx->cruid_specified = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600973 break;
Ronnie Sahlbergb946dbc2021-07-28 16:38:29 +1000974 case Opt_backupuid:
975 uid = make_kuid(current_user_ns(), result.uint_32);
976 if (!uid_valid(uid))
977 goto cifs_parse_mount_err;
978 ctx->backupuid = uid;
979 ctx->backupuid_specified = true;
980 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600981 case Opt_backupgid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000982 gid = make_kgid(current_user_ns(), result.uint_32);
983 if (!gid_valid(gid))
984 goto cifs_parse_mount_err;
985 ctx->backupgid = gid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600986 ctx->backupgid_specified = true;
987 break;
988 case Opt_gid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000989 gid = make_kgid(current_user_ns(), result.uint_32);
990 if (!gid_valid(gid))
991 goto cifs_parse_mount_err;
992 ctx->linux_gid = gid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600993 ctx->gid_specified = true;
994 break;
995 case Opt_port:
996 ctx->port = result.uint_32;
997 break;
998 case Opt_file_mode:
999 ctx->file_mode = result.uint_32;
1000 break;
1001 case Opt_dirmode:
1002 ctx->dir_mode = result.uint_32;
1003 break;
1004 case Opt_min_enc_offload:
1005 ctx->min_offload = result.uint_32;
1006 break;
1007 case Opt_blocksize:
1008 /*
1009 * inode blocksize realistically should never need to be
1010 * less than 16K or greater than 16M and default is 1MB.
1011 * Note that small inode block sizes (e.g. 64K) can lead
1012 * to very poor performance of common tools like cp and scp
1013 */
1014 if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||
1015 (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001016 cifs_errorf(fc, "%s: Invalid blocksize\n",
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001017 __func__);
1018 goto cifs_parse_mount_err;
1019 }
1020 ctx->bsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +10001021 ctx->got_bsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001022 break;
Steve Frenchb8d64f82021-04-24 21:46:23 -05001023 case Opt_rasize:
1024 /*
1025 * readahead size realistically should never need to be
1026 * less than 1M (CIFS_DEFAULT_IOSIZE) or greater than 32M
1027 * (perhaps an exception should be considered in the
1028 * for the case of a large number of channels
1029 * when multichannel is negotiated) since that would lead
1030 * to plenty of parallel I/O in flight to the server.
1031 * Note that smaller read ahead sizes would
1032 * hurt performance of common tools like cp and scp
1033 * which often trigger sequential i/o with read ahead
1034 */
1035 if ((result.uint_32 > (8 * SMB3_DEFAULT_IOSIZE)) ||
1036 (result.uint_32 < CIFS_DEFAULT_IOSIZE)) {
1037 cifs_errorf(fc, "%s: Invalid rasize %d vs. %d\n",
1038 __func__, result.uint_32, SMB3_DEFAULT_IOSIZE);
1039 goto cifs_parse_mount_err;
1040 }
1041 ctx->rasize = result.uint_32;
1042 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001043 case Opt_rsize:
1044 ctx->rsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +10001045 ctx->got_rsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001046 break;
1047 case Opt_wsize:
1048 ctx->wsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +10001049 ctx->got_wsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001050 break;
Steve French57804642021-02-24 12:12:53 -06001051 case Opt_acregmax:
1052 ctx->acregmax = HZ * result.uint_32;
1053 if (ctx->acregmax > CIFS_MAX_ACTIMEO) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001054 cifs_errorf(fc, "acregmax too large\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001055 goto cifs_parse_mount_err;
1056 }
1057 break;
Steve French4c9f9482021-02-23 15:50:57 -06001058 case Opt_acdirmax:
1059 ctx->acdirmax = HZ * result.uint_32;
1060 if (ctx->acdirmax > CIFS_MAX_ACTIMEO) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001061 cifs_errorf(fc, "acdirmax too large\n");
Steve French4c9f9482021-02-23 15:50:57 -06001062 goto cifs_parse_mount_err;
1063 }
1064 break;
Steve French57804642021-02-24 12:12:53 -06001065 case Opt_actimeo:
1066 if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001067 cifs_errorf(fc, "timeout too large\n");
Steve French57804642021-02-24 12:12:53 -06001068 goto cifs_parse_mount_err;
1069 }
1070 if ((ctx->acdirmax != CIFS_DEF_ACTIMEO) ||
1071 (ctx->acregmax != CIFS_DEF_ACTIMEO)) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001072 cifs_errorf(fc, "actimeo ignored since acregmax or acdirmax specified\n");
Steve French57804642021-02-24 12:12:53 -06001073 break;
1074 }
1075 ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
1076 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001077 case Opt_echo_interval:
1078 ctx->echo_interval = result.uint_32;
1079 break;
1080 case Opt_snapshot:
1081 ctx->snapshot_time = result.uint_32;
1082 break;
1083 case Opt_max_credits:
1084 if (result.uint_32 < 20 || result.uint_32 > 60000) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001085 cifs_errorf(fc, "%s: Invalid max_credits value\n",
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001086 __func__);
1087 goto cifs_parse_mount_err;
1088 }
1089 ctx->max_credits = result.uint_32;
1090 break;
1091 case Opt_max_channels:
1092 if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001093 cifs_errorf(fc, "%s: Invalid max_channels value, needs to be 1-%d\n",
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001094 __func__, CIFS_MAX_CHANNELS);
1095 goto cifs_parse_mount_err;
1096 }
1097 ctx->max_channels = result.uint_32;
Steve Frenchc1f8a392021-05-07 19:33:51 -05001098 /* If more than one channel requested ... they want multichan */
1099 if (result.uint_32 > 1)
1100 ctx->multichannel = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001101 break;
1102 case Opt_handletimeout:
1103 ctx->handle_timeout = result.uint_32;
1104 if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001105 cifs_errorf(fc, "Invalid handle cache timeout, longer than 16 minutes\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001106 goto cifs_parse_mount_err;
1107 }
1108 break;
1109 case Opt_source:
1110 kfree(ctx->UNC);
1111 ctx->UNC = NULL;
1112 switch (smb3_parse_devname(param->string, ctx)) {
1113 case 0:
1114 break;
1115 case -ENOMEM:
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001116 cifs_errorf(fc, "Unable to allocate memory for devname\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001117 goto cifs_parse_mount_err;
1118 case -EINVAL:
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001119 cifs_errorf(fc, "Malformed UNC in devname\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001120 goto cifs_parse_mount_err;
1121 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001122 cifs_errorf(fc, "Unknown error parsing devname\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001123 goto cifs_parse_mount_err;
1124 }
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +10001125 ctx->source = kstrdup(param->string, GFP_KERNEL);
1126 if (ctx->source == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001127 cifs_errorf(fc, "OOM when copying UNC string\n");
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +10001128 goto cifs_parse_mount_err;
1129 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001130 fc->source = kstrdup(param->string, GFP_KERNEL);
1131 if (fc->source == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001132 cifs_errorf(fc, "OOM when copying UNC string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001133 goto cifs_parse_mount_err;
1134 }
1135 break;
1136 case Opt_user:
1137 kfree(ctx->username);
1138 ctx->username = NULL;
1139 if (strlen(param->string) == 0) {
1140 /* null user, ie. anonymous authentication */
1141 ctx->nullauth = 1;
1142 break;
1143 }
1144
1145 if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) >
1146 CIFS_MAX_USERNAME_LEN) {
1147 pr_warn("username too long\n");
1148 goto cifs_parse_mount_err;
1149 }
1150 ctx->username = kstrdup(param->string, GFP_KERNEL);
1151 if (ctx->username == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001152 cifs_errorf(fc, "OOM when copying username string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001153 goto cifs_parse_mount_err;
1154 }
1155 break;
1156 case Opt_pass:
1157 kfree(ctx->password);
1158 ctx->password = NULL;
1159 if (strlen(param->string) == 0)
1160 break;
1161
1162 ctx->password = kstrdup(param->string, GFP_KERNEL);
1163 if (ctx->password == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001164 cifs_errorf(fc, "OOM when copying password string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001165 goto cifs_parse_mount_err;
1166 }
1167 break;
1168 case Opt_ip:
1169 if (strlen(param->string) == 0) {
1170 ctx->got_ip = false;
1171 break;
1172 }
1173 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
1174 param->string,
1175 strlen(param->string))) {
1176 pr_err("bad ip= option (%s)\n", param->string);
1177 goto cifs_parse_mount_err;
1178 }
1179 ctx->got_ip = true;
1180 break;
1181 case Opt_domain:
1182 if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN)
1183 == CIFS_MAX_DOMAINNAME_LEN) {
1184 pr_warn("domain name too long\n");
1185 goto cifs_parse_mount_err;
1186 }
1187
1188 kfree(ctx->domainname);
1189 ctx->domainname = kstrdup(param->string, GFP_KERNEL);
1190 if (ctx->domainname == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001191 cifs_errorf(fc, "OOM when copying domainname string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001192 goto cifs_parse_mount_err;
1193 }
1194 cifs_dbg(FYI, "Domain name set\n");
1195 break;
1196 case Opt_srcaddr:
1197 if (!cifs_convert_address(
1198 (struct sockaddr *)&ctx->srcaddr,
1199 param->string, strlen(param->string))) {
1200 pr_warn("Could not parse srcaddr: %s\n",
1201 param->string);
1202 goto cifs_parse_mount_err;
1203 }
1204 break;
1205 case Opt_iocharset:
1206 if (strnlen(param->string, 1024) >= 65) {
1207 pr_warn("iocharset name too long\n");
1208 goto cifs_parse_mount_err;
1209 }
1210
1211 if (strncasecmp(param->string, "default", 7) != 0) {
1212 kfree(ctx->iocharset);
1213 ctx->iocharset = kstrdup(param->string, GFP_KERNEL);
1214 if (ctx->iocharset == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001215 cifs_errorf(fc, "OOM when copying iocharset string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001216 goto cifs_parse_mount_err;
1217 }
1218 }
1219 /* if iocharset not set then load_nls_default
1220 * is used by caller
1221 */
Jiapeng Chonge83aa352021-05-19 18:47:07 +08001222 cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001223 break;
1224 case Opt_netbiosname:
1225 memset(ctx->source_rfc1001_name, 0x20,
1226 RFC1001_NAME_LEN);
1227 /*
1228 * FIXME: are there cases in which a comma can
1229 * be valid in workstation netbios name (and
1230 * need special handling)?
1231 */
1232 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1233 /* don't ucase netbiosname for user */
1234 if (param->string[i] == 0)
1235 break;
1236 ctx->source_rfc1001_name[i] = param->string[i];
1237 }
1238 /* The string has 16th byte zero still from
1239 * set at top of the function
1240 */
1241 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1242 pr_warn("netbiosname longer than 15 truncated\n");
1243 break;
1244 case Opt_servern:
1245 /* last byte, type, is 0x20 for servr type */
1246 memset(ctx->target_rfc1001_name, 0x20,
1247 RFC1001_NAME_LEN_WITH_NULL);
1248 /*
1249 * BB are there cases in which a comma can be valid in this
1250 * workstation netbios name (and need special handling)?
1251 */
1252
1253 /* user or mount helper must uppercase the netbios name */
1254 for (i = 0; i < 15; i++) {
1255 if (param->string[i] == 0)
1256 break;
1257 ctx->target_rfc1001_name[i] = param->string[i];
1258 }
1259
1260 /* The string has 16th byte zero still from set at top of function */
1261 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1262 pr_warn("server netbiosname longer than 15 truncated\n");
1263 break;
1264 case Opt_ver:
1265 /* version of mount userspace tools, not dialect */
1266 /* If interface changes in mount.cifs bump to new ver */
1267 if (strncasecmp(param->string, "1", 1) == 0) {
1268 if (strlen(param->string) > 1) {
1269 pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
1270 param->string);
1271 goto cifs_parse_mount_err;
1272 }
1273 /* This is the default */
1274 break;
1275 }
1276 /* For all other value, error */
1277 pr_warn("Invalid mount helper version specified\n");
1278 goto cifs_parse_mount_err;
1279 case Opt_vers:
1280 /* protocol version (dialect) */
Aurelien Apteld9a86922021-03-01 19:32:09 +01001281 if (cifs_parse_smb_version(fc, param->string, ctx, is_smb3) != 0)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001282 goto cifs_parse_mount_err;
1283 ctx->got_version = true;
1284 break;
1285 case Opt_sec:
Aurelien Apteld9a86922021-03-01 19:32:09 +01001286 if (cifs_parse_security_flavors(fc, param->string, ctx) != 0)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001287 goto cifs_parse_mount_err;
1288 break;
1289 case Opt_cache:
Aurelien Apteld9a86922021-03-01 19:32:09 +01001290 if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001291 goto cifs_parse_mount_err;
1292 break;
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001293 case Opt_witness:
1294#ifndef CONFIG_CIFS_SWN_UPCALL
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001295 cifs_errorf(fc, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001296 goto cifs_parse_mount_err;
1297#endif
1298 ctx->witness = true;
Steve Frenchdd538032020-12-14 20:15:12 -06001299 pr_warn_once("Witness protocol support is experimental\n");
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001300 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001301 case Opt_rootfs:
Aurelien Aptelaf3ef3b2021-03-18 19:17:10 +01001302#ifndef CONFIG_CIFS_ROOT
1303 cifs_dbg(VFS, "rootfs support requires CONFIG_CIFS_ROOT config option\n");
1304 goto cifs_parse_mount_err;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001305#endif
Aurelien Aptelaf3ef3b2021-03-18 19:17:10 +01001306 ctx->rootfs = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001307 break;
1308 case Opt_posixpaths:
1309 if (result.negated)
1310 ctx->posix_paths = 0;
1311 else
1312 ctx->posix_paths = 1;
1313 break;
1314 case Opt_unix:
Steve French7321be22021-08-23 13:52:12 -05001315 if (result.negated) {
1316 if (ctx->linux_ext == 1)
1317 pr_warn_once("conflicting posix mount options specified\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001318 ctx->linux_ext = 0;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001319 ctx->no_linux_ext = 1;
Steve French7321be22021-08-23 13:52:12 -05001320 } else {
1321 if (ctx->no_linux_ext == 1)
1322 pr_warn_once("conflicting posix mount options specified\n");
1323 ctx->linux_ext = 1;
1324 ctx->no_linux_ext = 0;
1325 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001326 break;
1327 case Opt_nocase:
1328 ctx->nocase = 1;
1329 break;
1330 case Opt_brl:
1331 if (result.negated) {
1332 /*
1333 * turn off mandatory locking in mode
1334 * if remote locking is turned off since the
1335 * local vfs will do advisory
1336 */
1337 if (ctx->file_mode ==
1338 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1339 ctx->file_mode = S_IALLUGO;
1340 ctx->nobrl = 1;
1341 } else
1342 ctx->nobrl = 0;
1343 break;
1344 case Opt_handlecache:
1345 if (result.negated)
1346 ctx->nohandlecache = 1;
1347 else
1348 ctx->nohandlecache = 0;
1349 break;
1350 case Opt_forcemandatorylock:
1351 ctx->mand_lock = 1;
1352 break;
1353 case Opt_setuids:
1354 ctx->setuids = result.negated;
1355 break;
1356 case Opt_intr:
1357 ctx->intr = !result.negated;
1358 break;
1359 case Opt_setuidfromacl:
1360 ctx->setuidfromacl = 1;
1361 break;
1362 case Opt_strictsync:
1363 ctx->nostrictsync = result.negated;
1364 break;
1365 case Opt_serverino:
1366 ctx->server_ino = !result.negated;
1367 break;
1368 case Opt_rwpidforward:
1369 ctx->rwpidforward = 1;
1370 break;
1371 case Opt_modesid:
1372 ctx->mode_ace = 1;
1373 break;
1374 case Opt_cifsacl:
1375 ctx->cifs_acl = !result.negated;
1376 break;
1377 case Opt_acl:
1378 ctx->no_psx_acl = result.negated;
1379 break;
1380 case Opt_locallease:
1381 ctx->local_lease = 1;
1382 break;
1383 case Opt_sign:
1384 ctx->sign = true;
1385 break;
1386 case Opt_ignore_signature:
1387 ctx->sign = true;
1388 ctx->ignore_signature = true;
1389 break;
1390 case Opt_seal:
1391 /* we do not do the following in secFlags because seal
1392 * is a per tree connection (mount) not a per socket
1393 * or per-smb connection option in the protocol
1394 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1395 */
1396 ctx->seal = 1;
1397 break;
1398 case Opt_noac:
1399 pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1400 break;
1401 case Opt_fsc:
1402#ifndef CONFIG_CIFS_FSCACHE
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001403 cifs_errorf(fc, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001404 goto cifs_parse_mount_err;
1405#endif
1406 ctx->fsc = true;
1407 break;
1408 case Opt_mfsymlinks:
1409 ctx->mfsymlinks = true;
1410 break;
1411 case Opt_multiuser:
1412 ctx->multiuser = true;
1413 break;
1414 case Opt_sloppy:
1415 ctx->sloppy = true;
1416 break;
1417 case Opt_nosharesock:
1418 ctx->nosharesock = true;
1419 break;
1420 case Opt_persistent:
1421 if (result.negated) {
Steve French27cf9482020-12-16 01:22:54 -06001422 ctx->nopersistent = true;
1423 if (ctx->persistent) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001424 cifs_errorf(fc, "persistenthandles mount options conflict\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001425 goto cifs_parse_mount_err;
1426 }
1427 } else {
Steve French27cf9482020-12-16 01:22:54 -06001428 ctx->persistent = true;
1429 if ((ctx->nopersistent) || (ctx->resilient)) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001430 cifs_errorf(fc, "persistenthandles mount options conflict\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001431 goto cifs_parse_mount_err;
1432 }
1433 }
1434 break;
1435 case Opt_resilient:
1436 if (result.negated) {
1437 ctx->resilient = false; /* already the default */
1438 } else {
1439 ctx->resilient = true;
1440 if (ctx->persistent) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001441 cifs_errorf(fc, "persistenthandles mount options conflict\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001442 goto cifs_parse_mount_err;
1443 }
1444 }
1445 break;
Steve French7ae5e582021-10-14 15:54:26 -05001446 case Opt_tcp_nodelay:
1447 /* tcp nodelay should not usually be needed since we CORK/UNCORK the socket */
1448 if (result.negated)
1449 ctx->sockopt_tcp_nodelay = false;
1450 else
1451 ctx->sockopt_tcp_nodelay = true;
1452 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001453 case Opt_domainauto:
1454 ctx->domainauto = true;
1455 break;
1456 case Opt_rdma:
1457 ctx->rdma = true;
1458 break;
1459 }
Steve French31f65512020-12-16 16:26:35 -06001460 /* case Opt_ignore: - is ignored as expected ... */
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001461
1462 return 0;
1463
1464 cifs_parse_mount_err:
Steve Frenchbd2f0b42021-01-28 16:43:03 -06001465 return -EINVAL;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001466}
1467
1468int smb3_init_fs_context(struct fs_context *fc)
1469{
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001470 int rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001471 struct smb3_fs_context *ctx;
1472 char *nodename = utsname()->nodename;
1473 int i;
1474
1475 ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001476 if (unlikely(!ctx)) {
1477 rc = -ENOMEM;
1478 goto err_exit;
1479 }
1480
1481 ctx->workstation_name = kstrdup(nodename, GFP_KERNEL);
1482 if (unlikely(!ctx->workstation_name)) {
1483 rc = -ENOMEM;
1484 goto err_exit;
1485 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001486
1487 /*
1488 * does not have to be perfect mapping since field is
1489 * informational, only used for servers that do not support
1490 * port 445 and it can be overridden at mount time
1491 */
1492 memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1493 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
1494 ctx->source_rfc1001_name[i] = toupper(nodename[i]);
1495
1496 ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1497 /*
1498 * null target name indicates to use *SMBSERVR default called name
1499 * if we end up sending RFC1001 session initialize
1500 */
1501 ctx->target_rfc1001_name[0] = 0;
1502 ctx->cred_uid = current_uid();
1503 ctx->linux_uid = current_uid();
1504 ctx->linux_gid = current_gid();
Steve Frenchb8d64f82021-04-24 21:46:23 -05001505 /* By default 4MB read ahead size, 1MB block size */
1506 ctx->bsize = CIFS_DEFAULT_IOSIZE; /* can improve cp performance significantly */
1507 ctx->rasize = 0; /* 0 = use default (ie negotiated rsize) for read ahead pages */
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001508
1509 /*
1510 * default to SFM style remapping of seven reserved characters
1511 * unless user overrides it or we negotiate CIFS POSIX where
1512 * it is unnecessary. Can not simultaneously use more than one mapping
1513 * since then readdir could list files that open could not open
1514 */
1515 ctx->remap = true;
1516
1517 /* default to only allowing write access to owner of the mount */
1518 ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1519
1520 /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1521 /* default is always to request posix paths. */
1522 ctx->posix_paths = 1;
1523 /* default to using server inode numbers where available */
1524 ctx->server_ino = 1;
1525
1526 /* default is to use strict cifs caching semantics */
1527 ctx->strict_io = true;
1528
Steve French57804642021-02-24 12:12:53 -06001529 ctx->acregmax = CIFS_DEF_ACTIMEO;
Steve French4c9f9482021-02-23 15:50:57 -06001530 ctx->acdirmax = CIFS_DEF_ACTIMEO;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001531
1532 /* Most clients set timeout to 0, allows server to use its default */
1533 ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1534
1535 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1536 ctx->ops = &smb30_operations;
1537 ctx->vals = &smbdefault_values;
1538
1539 ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1540
1541 /* default to no multichannel (single server connection) */
1542 ctx->multichannel = false;
1543 ctx->max_channels = 1;
1544
1545 ctx->backupuid_specified = false; /* no backup intent for a user */
1546 ctx->backupgid_specified = false; /* no backup intent for a group */
1547
1548/*
1549 * short int override_uid = -1;
1550 * short int override_gid = -1;
1551 * char *nodename = strdup(utsname()->nodename);
1552 * struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
1553 */
1554
1555 fc->fs_private = ctx;
1556 fc->ops = &smb3_fs_context_ops;
1557 return 0;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001558
1559err_exit:
1560 if (ctx) {
1561 kfree(ctx->workstation_name);
1562 kfree(ctx);
1563 }
1564
1565 return rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001566}
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001567
1568void
1569smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
1570{
1571 if (ctx == NULL)
1572 return;
1573
1574 /*
1575 * Make sure this stays in sync with smb3_fs_context_dup()
1576 */
1577 kfree(ctx->mount_options);
1578 ctx->mount_options = NULL;
1579 kfree(ctx->username);
1580 ctx->username = NULL;
1581 kfree_sensitive(ctx->password);
1582 ctx->password = NULL;
Shyam Prasad N7be32482021-10-14 11:52:39 +00001583 kfree(ctx->server_hostname);
1584 ctx->server_hostname = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001585 kfree(ctx->UNC);
1586 ctx->UNC = NULL;
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +10001587 kfree(ctx->source);
1588 ctx->source = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001589 kfree(ctx->domainname);
1590 ctx->domainname = NULL;
Shyam Prasad N49bd49f2021-11-05 19:03:57 +00001591 kfree(ctx->workstation_name);
1592 ctx->workstation_name = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001593 kfree(ctx->nodename);
1594 ctx->nodename = NULL;
1595 kfree(ctx->iocharset);
1596 ctx->iocharset = NULL;
1597 kfree(ctx->prepath);
1598 ctx->prepath = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001599}
1600
1601void
1602smb3_cleanup_fs_context(struct smb3_fs_context *ctx)
1603{
1604 if (!ctx)
1605 return;
1606 smb3_cleanup_fs_context_contents(ctx);
1607 kfree(ctx);
1608}
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001609
1610void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
1611{
1612 struct smb3_fs_context *ctx = cifs_sb->ctx;
1613
1614 if (ctx->nodfs)
1615 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
1616 else
1617 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS;
1618
1619 if (ctx->noperm)
1620 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1621 else
1622 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM;
1623
1624 if (ctx->setuids)
1625 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1626 else
1627 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID;
1628
1629 if (ctx->setuidfromacl)
1630 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
1631 else
1632 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL;
1633
1634 if (ctx->server_ino)
1635 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1636 else
1637 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
1638
1639 if (ctx->remap)
1640 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
1641 else
1642 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR;
1643
1644 if (ctx->sfu_remap)
1645 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1646 else
1647 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
1648
1649 if (ctx->no_xattr)
1650 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1651 else
1652 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR;
1653
1654 if (ctx->sfu_emul)
1655 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1656 else
1657 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL;
1658
1659 if (ctx->nobrl)
1660 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1661 else
1662 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL;
1663
1664 if (ctx->nohandlecache)
1665 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
1666 else
1667 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
1668
1669 if (ctx->nostrictsync)
1670 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
1671 else
1672 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC;
1673
1674 if (ctx->mand_lock)
1675 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
1676 else
1677 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL;
1678
1679 if (ctx->rwpidforward)
1680 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
1681 else
1682 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD;
1683
1684 if (ctx->mode_ace)
1685 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
1686 else
1687 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID;
1688
1689 if (ctx->cifs_acl)
1690 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1691 else
1692 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL;
1693
1694 if (ctx->backupuid_specified)
1695 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
1696 else
1697 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
1698
1699 if (ctx->backupgid_specified)
1700 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
1701 else
1702 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
1703
1704 if (ctx->override_uid)
1705 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
1706 else
1707 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID;
1708
1709 if (ctx->override_gid)
1710 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
1711 else
1712 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID;
1713
1714 if (ctx->dynperm)
1715 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
1716 else
1717 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM;
1718
1719 if (ctx->fsc)
1720 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
1721 else
1722 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE;
1723
1724 if (ctx->multiuser)
1725 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
1726 CIFS_MOUNT_NO_PERM);
1727 else
Ronnie Sahlberga0f85e32021-02-10 11:55:47 +10001728 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MULTIUSER;
1729
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001730
1731 if (ctx->strict_io)
1732 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
1733 else
1734 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO;
1735
1736 if (ctx->direct_io)
1737 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1738 else
1739 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO;
1740
1741 if (ctx->mfsymlinks)
1742 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
1743 else
1744 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS;
1745 if (ctx->mfsymlinks) {
1746 if (ctx->sfu_emul) {
1747 /*
1748 * Our SFU ("Services for Unix" emulation does not allow
1749 * creating symlinks but does allow reading existing SFU
1750 * symlinks (it does allow both creating and reading SFU
1751 * style mknod and FIFOs though). When "mfsymlinks" and
1752 * "sfu" are both enabled at the same time, it allows
1753 * reading both types of symlinks, but will only create
1754 * them with mfsymlinks format. This allows better
1755 * Apple compatibility (probably better for Samba too)
1756 * while still recognizing old Windows style symlinks.
1757 */
1758 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
1759 }
1760 }
Steve French087f7572021-04-29 00:18:43 -05001761 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SHUTDOWN;
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001762
1763 return;
1764}