blob: 4130908af8d77e4b0454b0f37a63449fee3a70c0 [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),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600119 fsparam_flag("domainauto", Opt_domainauto),
120 fsparam_flag("rdma", Opt_rdma),
121 fsparam_flag("modesid", Opt_modesid),
Steve French27cf9482020-12-16 01:22:54 -0600122 fsparam_flag("modefromsid", Opt_modesid),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600123 fsparam_flag("rootfs", Opt_rootfs),
124 fsparam_flag("compress", Opt_compress),
Samuel Cabrero0ac4e292020-12-11 22:59:29 -0600125 fsparam_flag("witness", Opt_witness),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600126
127 /* Mount options which take numeric value */
128 fsparam_u32("backupuid", Opt_backupuid),
129 fsparam_u32("backupgid", Opt_backupgid),
130 fsparam_u32("uid", Opt_uid),
131 fsparam_u32("cruid", Opt_cruid),
132 fsparam_u32("gid", Opt_gid),
133 fsparam_u32("file_mode", Opt_file_mode),
134 fsparam_u32("dirmode", Opt_dirmode),
135 fsparam_u32("dir_mode", Opt_dirmode),
136 fsparam_u32("port", Opt_port),
137 fsparam_u32("min_enc_offload", Opt_min_enc_offload),
Steve French27cf9482020-12-16 01:22:54 -0600138 fsparam_u32("esize", Opt_min_enc_offload),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600139 fsparam_u32("bsize", Opt_blocksize),
Steve Frenchb8d64f82021-04-24 21:46:23 -0500140 fsparam_u32("rasize", Opt_rasize),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600141 fsparam_u32("rsize", Opt_rsize),
142 fsparam_u32("wsize", Opt_wsize),
143 fsparam_u32("actimeo", Opt_actimeo),
Steve French4c9f9482021-02-23 15:50:57 -0600144 fsparam_u32("acdirmax", Opt_acdirmax),
Steve French57804642021-02-24 12:12:53 -0600145 fsparam_u32("acregmax", Opt_acregmax),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600146 fsparam_u32("echo_interval", Opt_echo_interval),
147 fsparam_u32("max_credits", Opt_max_credits),
148 fsparam_u32("handletimeout", Opt_handletimeout),
149 fsparam_u32("snapshot", Opt_snapshot),
150 fsparam_u32("max_channels", Opt_max_channels),
151
152 /* Mount options which take string value */
153 fsparam_string("source", Opt_source),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600154 fsparam_string("user", Opt_user),
155 fsparam_string("username", Opt_user),
156 fsparam_string("pass", Opt_pass),
157 fsparam_string("password", Opt_pass),
158 fsparam_string("ip", Opt_ip),
159 fsparam_string("addr", Opt_ip),
160 fsparam_string("domain", Opt_domain),
161 fsparam_string("dom", Opt_domain),
162 fsparam_string("srcaddr", Opt_srcaddr),
163 fsparam_string("iocharset", Opt_iocharset),
164 fsparam_string("netbiosname", Opt_netbiosname),
165 fsparam_string("servern", Opt_servern),
166 fsparam_string("ver", Opt_ver),
167 fsparam_string("vers", Opt_vers),
168 fsparam_string("sec", Opt_sec),
169 fsparam_string("cache", Opt_cache),
170
171 /* Arguments that should be ignored */
172 fsparam_flag("guest", Opt_ignore),
173 fsparam_flag("noatime", Opt_ignore),
174 fsparam_flag("relatime", Opt_ignore),
175 fsparam_flag("_netdev", Opt_ignore),
176 fsparam_flag_no("suid", Opt_ignore),
177 fsparam_flag_no("exec", Opt_ignore),
178 fsparam_flag_no("dev", Opt_ignore),
179 fsparam_flag_no("mand", Opt_ignore),
Adam Harvey19d51582021-01-27 13:44:35 -0800180 fsparam_flag_no("auto", Opt_ignore),
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600181 fsparam_string("cred", Opt_ignore),
182 fsparam_string("credentials", Opt_ignore),
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000183 /*
184 * UNC and prefixpath is now extracted from Opt_source
185 * in the new mount API so we can just ignore them going forward.
186 */
187 fsparam_string("unc", Opt_ignore),
Steve Frenchc9b8cd62021-01-28 11:20:22 -0600188 fsparam_string("prefixpath", Opt_ignore),
Dmitry Osipenko427c4f02020-12-14 14:37:45 +0300189 {}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600190};
191
Aurelien Apteld9a86922021-03-01 19:32:09 +0100192static int
193cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000194{
195
196 substring_t args[MAX_OPT_ARGS];
197
198 /*
199 * With mount options, the last one should win. Reset any existing
200 * settings back to default.
201 */
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600202 ctx->sectype = Unspecified;
203 ctx->sign = false;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000204
205 switch (match_token(value, cifs_secflavor_tokens, args)) {
206 case Opt_sec_krb5p:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100207 cifs_errorf(fc, "sec=krb5p is not supported!\n");
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000208 return 1;
209 case Opt_sec_krb5i:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600210 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000211 fallthrough;
212 case Opt_sec_krb5:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600213 ctx->sectype = Kerberos;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000214 break;
215 case Opt_sec_ntlmsspi:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600216 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000217 fallthrough;
218 case Opt_sec_ntlmssp:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600219 ctx->sectype = RawNTLMSSP;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000220 break;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000221 case Opt_sec_ntlmv2i:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600222 ctx->sign = true;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000223 fallthrough;
224 case Opt_sec_ntlmv2:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600225 ctx->sectype = NTLMv2;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000226 break;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000227 case Opt_sec_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600228 ctx->nullauth = 1;
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000229 break;
230 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100231 cifs_errorf(fc, "bad security option: %s\n", value);
Ronnie Sahlberg5c6e5aa2020-10-21 10:37:11 +1000232 return 1;
233 }
234
235 return 0;
236}
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000237
238static const match_table_t cifs_cacheflavor_tokens = {
239 { Opt_cache_loose, "loose" },
240 { Opt_cache_strict, "strict" },
241 { Opt_cache_none, "none" },
242 { Opt_cache_ro, "ro" },
243 { Opt_cache_rw, "singleclient" },
244 { Opt_cache_err, NULL }
245};
246
Aurelien Apteld9a86922021-03-01 19:32:09 +0100247static int
248cifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000249{
250 substring_t args[MAX_OPT_ARGS];
251
252 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
253 case Opt_cache_loose:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600254 ctx->direct_io = false;
255 ctx->strict_io = false;
256 ctx->cache_ro = false;
257 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000258 break;
259 case Opt_cache_strict:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600260 ctx->direct_io = false;
261 ctx->strict_io = true;
262 ctx->cache_ro = false;
263 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000264 break;
265 case Opt_cache_none:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600266 ctx->direct_io = true;
267 ctx->strict_io = false;
268 ctx->cache_ro = false;
269 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000270 break;
271 case Opt_cache_ro:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600272 ctx->direct_io = false;
273 ctx->strict_io = false;
274 ctx->cache_ro = true;
275 ctx->cache_rw = false;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000276 break;
277 case Opt_cache_rw:
Ronnie Sahlberg3fa1c6d2020-12-09 23:07:12 -0600278 ctx->direct_io = false;
279 ctx->strict_io = false;
280 ctx->cache_ro = false;
281 ctx->cache_rw = true;
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000282 break;
283 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100284 cifs_errorf(fc, "bad cache= option: %s\n", value);
Ronnie Sahlberg2f20f072020-10-21 11:30:35 +1000285 return 1;
286 }
287 return 0;
288}
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000289
290#define DUP_CTX_STR(field) \
291do { \
292 if (ctx->field) { \
293 new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC); \
294 if (new_ctx->field == NULL) { \
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000295 smb3_cleanup_fs_context_contents(new_ctx); \
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000296 return -ENOMEM; \
297 } \
298 } \
299} while (0)
300
301int
302smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)
303{
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000304 memcpy(new_ctx, ctx, sizeof(*ctx));
305 new_ctx->prepath = NULL;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600306 new_ctx->mount_options = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000307 new_ctx->nodename = NULL;
308 new_ctx->username = NULL;
309 new_ctx->password = NULL;
310 new_ctx->domainname = NULL;
311 new_ctx->UNC = NULL;
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000312 new_ctx->source = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000313 new_ctx->iocharset = NULL;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000314 /*
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000315 * Make sure to stay in sync with smb3_cleanup_fs_context_contents()
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000316 */
317 DUP_CTX_STR(prepath);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600318 DUP_CTX_STR(mount_options);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000319 DUP_CTX_STR(username);
320 DUP_CTX_STR(password);
Shyam Prasad N7be32482021-10-14 11:52:39 +0000321 DUP_CTX_STR(server_hostname);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000322 DUP_CTX_STR(UNC);
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000323 DUP_CTX_STR(source);
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000324 DUP_CTX_STR(domainname);
325 DUP_CTX_STR(nodename);
326 DUP_CTX_STR(iocharset);
327
Menglong Dongc13e7af2021-01-12 01:13:40 -0800328 return 0;
Ronnie Sahlberg837e3a12020-11-02 09:36:24 +1000329}
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000330
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600331static int
Aurelien Apteld9a86922021-03-01 19:32:09 +0100332cifs_parse_smb_version(struct fs_context *fc, char *value, struct smb3_fs_context *ctx, bool is_smb3)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600333{
334 substring_t args[MAX_OPT_ARGS];
335
336 switch (match_token(value, cifs_smb_version_tokens, args)) {
337#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
338 case Smb_1:
339 if (disable_legacy_dialects) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100340 cifs_errorf(fc, "mount with legacy dialect disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600341 return 1;
342 }
343 if (is_smb3) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100344 cifs_errorf(fc, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600345 return 1;
346 }
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100347 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 -0600348 ctx->ops = &smb1_operations;
349 ctx->vals = &smb1_values;
350 break;
351 case Smb_20:
352 if (disable_legacy_dialects) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100353 cifs_errorf(fc, "mount with legacy dialect disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600354 return 1;
355 }
356 if (is_smb3) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100357 cifs_errorf(fc, "vers=2.0 not permitted when mounting with smb3\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600358 return 1;
359 }
360 ctx->ops = &smb20_operations;
361 ctx->vals = &smb20_values;
362 break;
363#else
364 case Smb_1:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100365 cifs_errorf(fc, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600366 return 1;
367 case Smb_20:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100368 cifs_errorf(fc, "vers=2.0 mount not permitted when legacy dialects disabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600369 return 1;
370#endif /* CIFS_ALLOW_INSECURE_LEGACY */
371 case Smb_21:
372 ctx->ops = &smb21_operations;
373 ctx->vals = &smb21_values;
374 break;
375 case Smb_30:
376 ctx->ops = &smb30_operations;
377 ctx->vals = &smb30_values;
378 break;
379 case Smb_302:
380 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
381 ctx->vals = &smb302_values;
382 break;
383 case Smb_311:
384 ctx->ops = &smb311_operations;
385 ctx->vals = &smb311_values;
386 break;
387 case Smb_3any:
388 ctx->ops = &smb30_operations; /* currently identical with 3.0 */
389 ctx->vals = &smb3any_values;
390 break;
391 case Smb_default:
Steve French6dffa4c2021-02-02 00:03:58 -0600392 ctx->ops = &smb30_operations;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600393 ctx->vals = &smbdefault_values;
394 break;
395 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100396 cifs_errorf(fc, "Unknown vers= option specified: %s\n", value);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600397 return 1;
398 }
399 return 0;
400}
401
Ronnie Sahlberg0d4873f2021-01-28 21:35:10 -0600402int smb3_parse_opt(const char *options, const char *key, char **val)
403{
404 int rc = -ENOENT;
405 char *opts, *orig, *p;
406
407 orig = opts = kstrdup(options, GFP_KERNEL);
408 if (!opts)
409 return -ENOMEM;
410
411 while ((p = strsep(&opts, ","))) {
412 char *nval;
413
414 if (!*p)
415 continue;
416 if (strncasecmp(p, key, strlen(key)))
417 continue;
418 nval = strchr(p, '=');
419 if (nval) {
420 if (nval == p)
421 continue;
422 *nval++ = 0;
Al Viro8d767222021-03-05 15:02:34 -0500423 *val = kstrdup(nval, GFP_KERNEL);
Ronnie Sahlberg0d4873f2021-01-28 21:35:10 -0600424 rc = !*val ? -ENOMEM : 0;
425 goto out;
426 }
427 }
428out:
429 kfree(orig);
430 return rc;
431}
432
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000433/*
434 * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath
435 * fields with the result. Returns 0 on success and an error otherwise
436 * (e.g. ENOMEM or EINVAL)
437 */
438int
439smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
440{
441 char *pos;
442 const char *delims = "/\\";
443 size_t len;
444
445 if (unlikely(!devname || !*devname)) {
446 cifs_dbg(VFS, "Device name not specified\n");
447 return -EINVAL;
448 }
449
450 /* make sure we have a valid UNC double delimiter prefix */
451 len = strspn(devname, delims);
452 if (len != 2)
453 return -EINVAL;
454
455 /* find delimiter between host and sharename */
456 pos = strpbrk(devname + 2, delims);
457 if (!pos)
458 return -EINVAL;
459
Shyam Prasad N7be32482021-10-14 11:52:39 +0000460 /* record the server hostname */
461 ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL);
462 if (!ctx->server_hostname)
463 return -ENOMEM;
464
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000465 /* skip past delimiter */
466 ++pos;
467
468 /* now go until next delimiter or end of string */
469 len = strcspn(pos, delims);
470
471 /* move "pos" up to delimiter or NULL */
472 pos += len;
Paulo Alcantara5c1acf32021-05-03 11:55:26 -0300473 kfree(ctx->UNC);
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000474 ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
475 if (!ctx->UNC)
476 return -ENOMEM;
477
478 convert_delimiter(ctx->UNC, '\\');
479
480 /* skip any delimiter */
481 if (*pos == '/' || *pos == '\\')
482 pos++;
483
Paulo Alcantara5c1acf32021-05-03 11:55:26 -0300484 kfree(ctx->prepath);
485 ctx->prepath = NULL;
486
Ronnie Sahlberg66e7b092020-11-05 13:58:14 +1000487 /* If pos is NULL then no prepath */
488 if (!*pos)
489 return 0;
490
491 ctx->prepath = kstrdup(pos, GFP_KERNEL);
492 if (!ctx->prepath)
493 return -ENOMEM;
494
495 return 0;
496}
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600497
498static void smb3_fs_context_free(struct fs_context *fc);
499static int smb3_fs_context_parse_param(struct fs_context *fc,
500 struct fs_parameter *param);
501static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
502 void *data);
503static int smb3_get_tree(struct fs_context *fc);
504static int smb3_reconfigure(struct fs_context *fc);
505
506static const struct fs_context_operations smb3_fs_context_ops = {
507 .free = smb3_fs_context_free,
508 .parse_param = smb3_fs_context_parse_param,
509 .parse_monolithic = smb3_fs_context_parse_monolithic,
510 .get_tree = smb3_get_tree,
511 .reconfigure = smb3_reconfigure,
512};
513
514/*
515 * Parse a monolithic block of data from sys_mount().
516 * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data
517 * @ctx: The superblock configuration to fill in.
518 * @data: The data to parse
519 *
520 * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be
521 * called from the ->monolithic_mount_data() fs_context operation.
522 *
523 * Returns 0 on success or the error returned by the ->parse_option() fs_context
524 * operation on failure.
525 */
526static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
527 void *data)
528{
529 struct smb3_fs_context *ctx = smb3_fc2context(fc);
530 char *options = data, *key;
531 int ret = 0;
532
533 if (!options)
534 return 0;
535
536 ctx->mount_options = kstrdup(data, GFP_KERNEL);
537 if (ctx->mount_options == NULL)
538 return -ENOMEM;
539
540 ret = security_sb_eat_lsm_opts(options, &fc->security);
541 if (ret)
542 return ret;
543
544 /* BB Need to add support for sep= here TBD */
545 while ((key = strsep(&options, ",")) != NULL) {
Ronnie Sahlbergd08395a2021-02-25 17:36:27 +1000546 size_t len;
547 char *value;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600548
Ronnie Sahlbergd08395a2021-02-25 17:36:27 +1000549 if (*key == 0)
550 break;
551
552 /* Check if following character is the deliminator If yes,
553 * we have encountered a double deliminator reset the NULL
554 * character to the deliminator
555 */
556 while (options && options[0] == ',') {
557 len = strlen(key);
558 strcpy(key + len, options);
559 options = strchr(options, ',');
560 if (options)
561 *options++ = 0;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600562 }
Ronnie Sahlbergd08395a2021-02-25 17:36:27 +1000563
564
565 len = 0;
566 value = strchr(key, '=');
567 if (value) {
568 if (value == key)
569 continue;
570 *value++ = 0;
571 len = strlen(value);
572 }
573
574 ret = vfs_parse_fs_string(fc, key, value, len);
575 if (ret < 0)
576 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600577 }
578
579 return ret;
580}
581
582/*
583 * Validate the preparsed information in the config.
584 */
585static int smb3_fs_context_validate(struct fs_context *fc)
586{
587 struct smb3_fs_context *ctx = smb3_fc2context(fc);
588
589 if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100590 cifs_errorf(fc, "SMB Direct requires Version >=3.0\n");
Steve Frenchbd2f0b42021-01-28 16:43:03 -0600591 return -EOPNOTSUPP;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600592 }
593
594#ifndef CONFIG_KEYS
595 /* Muliuser mounts require CONFIG_KEYS support */
596 if (ctx->multiuser) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100597 cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600598 return -1;
599 }
600#endif
601
602 if (ctx->got_version == false)
603 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");
604
605
606 if (!ctx->UNC) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100607 cifs_errorf(fc, "CIFS mount error: No usable UNC path provided in device string!\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600608 return -1;
609 }
610
611 /* make sure UNC has a share name */
612 if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100613 cifs_errorf(fc, "Malformed UNC. Unable to find share name.\n");
Steve Frenchbd2f0b42021-01-28 16:43:03 -0600614 return -ENOENT;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600615 }
616
617 if (!ctx->got_ip) {
618 int len;
619 const char *slash;
620
621 /* No ip= option specified? Try to get it from UNC */
622 /* Use the address part of the UNC. */
623 slash = strchr(&ctx->UNC[2], '\\');
624 len = slash - &ctx->UNC[2];
625 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
626 &ctx->UNC[2], len)) {
627 pr_err("Unable to determine destination address\n");
Steve Frenchbd2f0b42021-01-28 16:43:03 -0600628 return -EHOSTUNREACH;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600629 }
630 }
631
632 /* set the port that we got earlier */
633 cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
634
635 if (ctx->override_uid && !ctx->uid_specified) {
636 ctx->override_uid = 0;
637 pr_notice("ignoring forceuid mount option specified with no uid= option\n");
638 }
639
640 if (ctx->override_gid && !ctx->gid_specified) {
641 ctx->override_gid = 0;
642 pr_notice("ignoring forcegid mount option specified with no gid= option\n");
643 }
644
645 return 0;
646}
647
648static int smb3_get_tree_common(struct fs_context *fc)
649{
650 struct smb3_fs_context *ctx = smb3_fc2context(fc);
651 struct dentry *root;
652 int rc = 0;
653
654 root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);
655 if (IS_ERR(root))
656 return PTR_ERR(root);
657
658 fc->root = root;
659
660 return rc;
661}
662
663/*
664 * Create an SMB3 superblock from the parameters passed.
665 */
666static int smb3_get_tree(struct fs_context *fc)
667{
668 int err = smb3_fs_context_validate(fc);
669
670 if (err)
671 return err;
672 return smb3_get_tree_common(fc);
673}
674
675static void smb3_fs_context_free(struct fs_context *fc)
676{
677 struct smb3_fs_context *ctx = smb3_fc2context(fc);
678
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +1000679 smb3_cleanup_fs_context(ctx);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600680}
681
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000682/*
683 * Compare the old and new proposed context during reconfigure
684 * and check if the changes are compatible.
685 */
Aurelien Apteld9a86922021-03-01 19:32:09 +0100686static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
687 struct smb3_fs_context *new_ctx,
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000688 struct smb3_fs_context *old_ctx)
689{
Ronnie Sahlberg531f03b2020-12-14 16:40:23 +1000690 if (new_ctx->posix_paths != old_ctx->posix_paths) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100691 cifs_errorf(fc, "can not change posixpaths during remount\n");
Ronnie Sahlberg531f03b2020-12-14 16:40:23 +1000692 return -EINVAL;
693 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000694 if (new_ctx->sectype != old_ctx->sectype) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100695 cifs_errorf(fc, "can not change sec during remount\n");
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000696 return -EINVAL;
697 }
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000698 if (new_ctx->multiuser != old_ctx->multiuser) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100699 cifs_errorf(fc, "can not change multiuser during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000700 return -EINVAL;
701 }
702 if (new_ctx->UNC &&
703 (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100704 cifs_errorf(fc, "can not change UNC during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000705 return -EINVAL;
706 }
707 if (new_ctx->username &&
708 (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100709 cifs_errorf(fc, "can not change username during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000710 return -EINVAL;
711 }
712 if (new_ctx->password &&
713 (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100714 cifs_errorf(fc, "can not change password during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000715 return -EINVAL;
716 }
717 if (new_ctx->domainname &&
718 (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100719 cifs_errorf(fc, "can not change domainname during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000720 return -EINVAL;
721 }
722 if (new_ctx->nodename &&
723 (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100724 cifs_errorf(fc, "can not change nodename during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000725 return -EINVAL;
726 }
727 if (new_ctx->iocharset &&
728 (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100729 cifs_errorf(fc, "can not change iocharset during remount\n");
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000730 return -EINVAL;
731 }
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000732
733 return 0;
734}
735
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000736#define STEAL_STRING(cifs_sb, ctx, field) \
737do { \
738 kfree(ctx->field); \
739 ctx->field = cifs_sb->ctx->field; \
740 cifs_sb->ctx->field = NULL; \
741} while (0)
742
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600743static int smb3_reconfigure(struct fs_context *fc)
744{
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000745 struct smb3_fs_context *ctx = smb3_fc2context(fc);
746 struct dentry *root = fc->root;
747 struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
748 int rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600749
Aurelien Apteld9a86922021-03-01 19:32:09 +0100750 rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000751 if (rc)
752 return rc;
753
754 /*
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000755 * We can not change UNC/username/password/domainname/nodename/iocharset
756 * during reconnect so ignore what we have in the new context and
757 * just use what we already have in cifs_sb->ctx.
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000758 */
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000759 STEAL_STRING(cifs_sb, ctx, UNC);
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +1000760 STEAL_STRING(cifs_sb, ctx, source);
Ronnie Sahlberg9ccecae2020-12-14 16:40:19 +1000761 STEAL_STRING(cifs_sb, ctx, username);
762 STEAL_STRING(cifs_sb, ctx, password);
763 STEAL_STRING(cifs_sb, ctx, domainname);
764 STEAL_STRING(cifs_sb, ctx, nodename);
765 STEAL_STRING(cifs_sb, ctx, iocharset);
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000766
Steve French2d060492020-12-16 18:04:27 -0600767 /* if rsize or wsize not passed in on remount, use previous values */
768 if (ctx->rsize == 0)
769 ctx->rsize = cifs_sb->ctx->rsize;
770 if (ctx->wsize == 0)
771 ctx->wsize = cifs_sb->ctx->wsize;
772
773
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000774 smb3_cleanup_fs_context_contents(cifs_sb->ctx);
775 rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
Ronnie Sahlberg1cb6c3d2020-12-14 16:40:26 +1000776 smb3_update_mnt_flags(cifs_sb);
Paulo Alcantarab6236612021-07-16 03:26:41 -0300777#ifdef CONFIG_CIFS_DFS_UPCALL
778 if (!rc)
779 rc = dfs_cache_remount_fs(cifs_sb);
780#endif
Ronnie Sahlbergd6a78782020-12-14 16:40:18 +1000781
782 return rc;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600783}
784
785static int smb3_fs_context_parse_param(struct fs_context *fc,
786 struct fs_parameter *param)
787{
788 struct fs_parse_result result;
789 struct smb3_fs_context *ctx = smb3_fc2context(fc);
790 int i, opt;
791 bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
792 bool skip_parsing = false;
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000793 kuid_t uid;
794 kgid_t gid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600795
796 cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
797
798 /*
799 * fs_parse can not handle string options with an empty value so
800 * we will need special handling of them.
801 */
802 if (param->type == fs_value_is_string && param->string[0] == 0) {
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000803 if (!strcmp("pass", param->key) || !strcmp("password", param->key)) {
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600804 skip_parsing = true;
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000805 opt = Opt_pass;
Steve French31f65512020-12-16 16:26:35 -0600806 } else if (!strcmp("user", param->key) || !strcmp("username", param->key)) {
807 skip_parsing = true;
808 opt = Opt_user;
Ronnie Sahlberg5c4b6422020-12-14 16:40:27 +1000809 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600810 }
811
812 if (!skip_parsing) {
813 opt = fs_parse(fc, smb3_fs_parameters, param, &result);
814 if (opt < 0)
815 return ctx->sloppy ? 1 : opt;
816 }
817
818 switch (opt) {
819 case Opt_compress:
820 ctx->compression = UNKNOWN_TYPE;
821 cifs_dbg(VFS,
822 "SMB3 compression support is experimental\n");
823 break;
824 case Opt_nodfs:
825 ctx->nodfs = 1;
826 break;
827 case Opt_hard:
828 if (result.negated)
829 ctx->retry = 0;
830 else
831 ctx->retry = 1;
832 break;
833 case Opt_soft:
834 if (result.negated)
835 ctx->retry = 1;
836 else
837 ctx->retry = 0;
838 break;
839 case Opt_mapposix:
840 if (result.negated)
841 ctx->remap = false;
842 else {
843 ctx->remap = true;
844 ctx->sfu_remap = false; /* disable SFU mapping */
845 }
846 break;
847 case Opt_user_xattr:
848 if (result.negated)
849 ctx->no_xattr = 1;
850 else
851 ctx->no_xattr = 0;
852 break;
853 case Opt_forceuid:
854 if (result.negated)
855 ctx->override_uid = 0;
856 else
857 ctx->override_uid = 1;
858 break;
859 case Opt_forcegid:
860 if (result.negated)
861 ctx->override_gid = 0;
862 else
863 ctx->override_gid = 1;
864 break;
865 case Opt_perm:
866 if (result.negated)
867 ctx->noperm = 1;
868 else
869 ctx->noperm = 0;
870 break;
871 case Opt_dynperm:
872 if (result.negated)
873 ctx->dynperm = 0;
874 else
875 ctx->dynperm = 1;
876 break;
877 case Opt_sfu:
878 if (result.negated)
879 ctx->sfu_emul = 0;
880 else
881 ctx->sfu_emul = 1;
882 break;
883 case Opt_noblocksend:
884 ctx->noblocksnd = 1;
885 break;
886 case Opt_noautotune:
887 ctx->noautotune = 1;
888 break;
889 case Opt_nolease:
890 ctx->no_lease = 1;
891 break;
892 case Opt_nodelete:
893 ctx->nodelete = 1;
894 break;
895 case Opt_multichannel:
896 if (result.negated) {
897 ctx->multichannel = false;
898 ctx->max_channels = 1;
899 } else {
900 ctx->multichannel = true;
901 /* if number of channels not specified, default to 2 */
902 if (ctx->max_channels < 2)
903 ctx->max_channels = 2;
904 }
905 break;
906 case Opt_uid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000907 uid = make_kuid(current_user_ns(), result.uint_32);
908 if (!uid_valid(uid))
909 goto cifs_parse_mount_err;
910 ctx->linux_uid = uid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600911 ctx->uid_specified = true;
912 break;
913 case Opt_cruid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000914 uid = make_kuid(current_user_ns(), result.uint_32);
915 if (!uid_valid(uid))
916 goto cifs_parse_mount_err;
917 ctx->cred_uid = uid;
918 ctx->cruid_specified = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600919 break;
Ronnie Sahlbergb946dbc2021-07-28 16:38:29 +1000920 case Opt_backupuid:
921 uid = make_kuid(current_user_ns(), result.uint_32);
922 if (!uid_valid(uid))
923 goto cifs_parse_mount_err;
924 ctx->backupuid = uid;
925 ctx->backupuid_specified = true;
926 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600927 case Opt_backupgid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000928 gid = make_kgid(current_user_ns(), result.uint_32);
929 if (!gid_valid(gid))
930 goto cifs_parse_mount_err;
931 ctx->backupgid = gid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600932 ctx->backupgid_specified = true;
933 break;
934 case Opt_gid:
Ronnie Sahlberge0a3cbc2021-07-08 09:24:16 +1000935 gid = make_kgid(current_user_ns(), result.uint_32);
936 if (!gid_valid(gid))
937 goto cifs_parse_mount_err;
938 ctx->linux_gid = gid;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600939 ctx->gid_specified = true;
940 break;
941 case Opt_port:
942 ctx->port = result.uint_32;
943 break;
944 case Opt_file_mode:
945 ctx->file_mode = result.uint_32;
946 break;
947 case Opt_dirmode:
948 ctx->dir_mode = result.uint_32;
949 break;
950 case Opt_min_enc_offload:
951 ctx->min_offload = result.uint_32;
952 break;
953 case Opt_blocksize:
954 /*
955 * inode blocksize realistically should never need to be
956 * less than 16K or greater than 16M and default is 1MB.
957 * Note that small inode block sizes (e.g. 64K) can lead
958 * to very poor performance of common tools like cp and scp
959 */
960 if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||
961 (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +0100962 cifs_errorf(fc, "%s: Invalid blocksize\n",
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600963 __func__);
964 goto cifs_parse_mount_err;
965 }
966 ctx->bsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000967 ctx->got_bsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600968 break;
Steve Frenchb8d64f82021-04-24 21:46:23 -0500969 case Opt_rasize:
970 /*
971 * readahead size realistically should never need to be
972 * less than 1M (CIFS_DEFAULT_IOSIZE) or greater than 32M
973 * (perhaps an exception should be considered in the
974 * for the case of a large number of channels
975 * when multichannel is negotiated) since that would lead
976 * to plenty of parallel I/O in flight to the server.
977 * Note that smaller read ahead sizes would
978 * hurt performance of common tools like cp and scp
979 * which often trigger sequential i/o with read ahead
980 */
981 if ((result.uint_32 > (8 * SMB3_DEFAULT_IOSIZE)) ||
982 (result.uint_32 < CIFS_DEFAULT_IOSIZE)) {
983 cifs_errorf(fc, "%s: Invalid rasize %d vs. %d\n",
984 __func__, result.uint_32, SMB3_DEFAULT_IOSIZE);
985 goto cifs_parse_mount_err;
986 }
987 ctx->rasize = result.uint_32;
988 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600989 case Opt_rsize:
990 ctx->rsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000991 ctx->got_rsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600992 break;
993 case Opt_wsize:
994 ctx->wsize = result.uint_32;
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +1000995 ctx->got_wsize = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -0600996 break;
Steve French57804642021-02-24 12:12:53 -0600997 case Opt_acregmax:
998 ctx->acregmax = HZ * result.uint_32;
999 if (ctx->acregmax > CIFS_MAX_ACTIMEO) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001000 cifs_errorf(fc, "acregmax too large\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001001 goto cifs_parse_mount_err;
1002 }
1003 break;
Steve French4c9f9482021-02-23 15:50:57 -06001004 case Opt_acdirmax:
1005 ctx->acdirmax = HZ * result.uint_32;
1006 if (ctx->acdirmax > CIFS_MAX_ACTIMEO) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001007 cifs_errorf(fc, "acdirmax too large\n");
Steve French4c9f9482021-02-23 15:50:57 -06001008 goto cifs_parse_mount_err;
1009 }
1010 break;
Steve French57804642021-02-24 12:12:53 -06001011 case Opt_actimeo:
1012 if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001013 cifs_errorf(fc, "timeout too large\n");
Steve French57804642021-02-24 12:12:53 -06001014 goto cifs_parse_mount_err;
1015 }
1016 if ((ctx->acdirmax != CIFS_DEF_ACTIMEO) ||
1017 (ctx->acregmax != CIFS_DEF_ACTIMEO)) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001018 cifs_errorf(fc, "actimeo ignored since acregmax or acdirmax specified\n");
Steve French57804642021-02-24 12:12:53 -06001019 break;
1020 }
1021 ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
1022 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001023 case Opt_echo_interval:
1024 ctx->echo_interval = result.uint_32;
1025 break;
1026 case Opt_snapshot:
1027 ctx->snapshot_time = result.uint_32;
1028 break;
1029 case Opt_max_credits:
1030 if (result.uint_32 < 20 || result.uint_32 > 60000) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001031 cifs_errorf(fc, "%s: Invalid max_credits value\n",
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001032 __func__);
1033 goto cifs_parse_mount_err;
1034 }
1035 ctx->max_credits = result.uint_32;
1036 break;
1037 case Opt_max_channels:
1038 if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001039 cifs_errorf(fc, "%s: Invalid max_channels value, needs to be 1-%d\n",
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001040 __func__, CIFS_MAX_CHANNELS);
1041 goto cifs_parse_mount_err;
1042 }
1043 ctx->max_channels = result.uint_32;
Steve Frenchc1f8a392021-05-07 19:33:51 -05001044 /* If more than one channel requested ... they want multichan */
1045 if (result.uint_32 > 1)
1046 ctx->multichannel = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001047 break;
1048 case Opt_handletimeout:
1049 ctx->handle_timeout = result.uint_32;
1050 if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001051 cifs_errorf(fc, "Invalid handle cache timeout, longer than 16 minutes\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001052 goto cifs_parse_mount_err;
1053 }
1054 break;
1055 case Opt_source:
1056 kfree(ctx->UNC);
1057 ctx->UNC = NULL;
1058 switch (smb3_parse_devname(param->string, ctx)) {
1059 case 0:
1060 break;
1061 case -ENOMEM:
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001062 cifs_errorf(fc, "Unable to allocate memory for devname\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001063 goto cifs_parse_mount_err;
1064 case -EINVAL:
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001065 cifs_errorf(fc, "Malformed UNC in devname\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001066 goto cifs_parse_mount_err;
1067 default:
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001068 cifs_errorf(fc, "Unknown error parsing devname\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001069 goto cifs_parse_mount_err;
1070 }
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +10001071 ctx->source = kstrdup(param->string, GFP_KERNEL);
1072 if (ctx->source == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001073 cifs_errorf(fc, "OOM when copying UNC string\n");
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +10001074 goto cifs_parse_mount_err;
1075 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001076 fc->source = kstrdup(param->string, GFP_KERNEL);
1077 if (fc->source == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001078 cifs_errorf(fc, "OOM when copying UNC string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001079 goto cifs_parse_mount_err;
1080 }
1081 break;
1082 case Opt_user:
1083 kfree(ctx->username);
1084 ctx->username = NULL;
1085 if (strlen(param->string) == 0) {
1086 /* null user, ie. anonymous authentication */
1087 ctx->nullauth = 1;
1088 break;
1089 }
1090
1091 if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) >
1092 CIFS_MAX_USERNAME_LEN) {
1093 pr_warn("username too long\n");
1094 goto cifs_parse_mount_err;
1095 }
1096 ctx->username = kstrdup(param->string, GFP_KERNEL);
1097 if (ctx->username == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001098 cifs_errorf(fc, "OOM when copying username string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001099 goto cifs_parse_mount_err;
1100 }
1101 break;
1102 case Opt_pass:
1103 kfree(ctx->password);
1104 ctx->password = NULL;
1105 if (strlen(param->string) == 0)
1106 break;
1107
1108 ctx->password = kstrdup(param->string, GFP_KERNEL);
1109 if (ctx->password == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001110 cifs_errorf(fc, "OOM when copying password string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001111 goto cifs_parse_mount_err;
1112 }
1113 break;
1114 case Opt_ip:
1115 if (strlen(param->string) == 0) {
1116 ctx->got_ip = false;
1117 break;
1118 }
1119 if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
1120 param->string,
1121 strlen(param->string))) {
1122 pr_err("bad ip= option (%s)\n", param->string);
1123 goto cifs_parse_mount_err;
1124 }
1125 ctx->got_ip = true;
1126 break;
1127 case Opt_domain:
1128 if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN)
1129 == CIFS_MAX_DOMAINNAME_LEN) {
1130 pr_warn("domain name too long\n");
1131 goto cifs_parse_mount_err;
1132 }
1133
1134 kfree(ctx->domainname);
1135 ctx->domainname = kstrdup(param->string, GFP_KERNEL);
1136 if (ctx->domainname == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001137 cifs_errorf(fc, "OOM when copying domainname string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001138 goto cifs_parse_mount_err;
1139 }
1140 cifs_dbg(FYI, "Domain name set\n");
1141 break;
1142 case Opt_srcaddr:
1143 if (!cifs_convert_address(
1144 (struct sockaddr *)&ctx->srcaddr,
1145 param->string, strlen(param->string))) {
1146 pr_warn("Could not parse srcaddr: %s\n",
1147 param->string);
1148 goto cifs_parse_mount_err;
1149 }
1150 break;
1151 case Opt_iocharset:
1152 if (strnlen(param->string, 1024) >= 65) {
1153 pr_warn("iocharset name too long\n");
1154 goto cifs_parse_mount_err;
1155 }
1156
1157 if (strncasecmp(param->string, "default", 7) != 0) {
1158 kfree(ctx->iocharset);
1159 ctx->iocharset = kstrdup(param->string, GFP_KERNEL);
1160 if (ctx->iocharset == NULL) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001161 cifs_errorf(fc, "OOM when copying iocharset string\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001162 goto cifs_parse_mount_err;
1163 }
1164 }
1165 /* if iocharset not set then load_nls_default
1166 * is used by caller
1167 */
Jiapeng Chonge83aa352021-05-19 18:47:07 +08001168 cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001169 break;
1170 case Opt_netbiosname:
1171 memset(ctx->source_rfc1001_name, 0x20,
1172 RFC1001_NAME_LEN);
1173 /*
1174 * FIXME: are there cases in which a comma can
1175 * be valid in workstation netbios name (and
1176 * need special handling)?
1177 */
1178 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1179 /* don't ucase netbiosname for user */
1180 if (param->string[i] == 0)
1181 break;
1182 ctx->source_rfc1001_name[i] = param->string[i];
1183 }
1184 /* The string has 16th byte zero still from
1185 * set at top of the function
1186 */
1187 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1188 pr_warn("netbiosname longer than 15 truncated\n");
1189 break;
1190 case Opt_servern:
1191 /* last byte, type, is 0x20 for servr type */
1192 memset(ctx->target_rfc1001_name, 0x20,
1193 RFC1001_NAME_LEN_WITH_NULL);
1194 /*
1195 * BB are there cases in which a comma can be valid in this
1196 * workstation netbios name (and need special handling)?
1197 */
1198
1199 /* user or mount helper must uppercase the netbios name */
1200 for (i = 0; i < 15; i++) {
1201 if (param->string[i] == 0)
1202 break;
1203 ctx->target_rfc1001_name[i] = param->string[i];
1204 }
1205
1206 /* The string has 16th byte zero still from set at top of function */
1207 if (i == RFC1001_NAME_LEN && param->string[i] != 0)
1208 pr_warn("server netbiosname longer than 15 truncated\n");
1209 break;
1210 case Opt_ver:
1211 /* version of mount userspace tools, not dialect */
1212 /* If interface changes in mount.cifs bump to new ver */
1213 if (strncasecmp(param->string, "1", 1) == 0) {
1214 if (strlen(param->string) > 1) {
1215 pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
1216 param->string);
1217 goto cifs_parse_mount_err;
1218 }
1219 /* This is the default */
1220 break;
1221 }
1222 /* For all other value, error */
1223 pr_warn("Invalid mount helper version specified\n");
1224 goto cifs_parse_mount_err;
1225 case Opt_vers:
1226 /* protocol version (dialect) */
Aurelien Apteld9a86922021-03-01 19:32:09 +01001227 if (cifs_parse_smb_version(fc, param->string, ctx, is_smb3) != 0)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001228 goto cifs_parse_mount_err;
1229 ctx->got_version = true;
1230 break;
1231 case Opt_sec:
Aurelien Apteld9a86922021-03-01 19:32:09 +01001232 if (cifs_parse_security_flavors(fc, param->string, ctx) != 0)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001233 goto cifs_parse_mount_err;
1234 break;
1235 case Opt_cache:
Aurelien Apteld9a86922021-03-01 19:32:09 +01001236 if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0)
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001237 goto cifs_parse_mount_err;
1238 break;
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001239 case Opt_witness:
1240#ifndef CONFIG_CIFS_SWN_UPCALL
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001241 cifs_errorf(fc, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001242 goto cifs_parse_mount_err;
1243#endif
1244 ctx->witness = true;
Steve Frenchdd538032020-12-14 20:15:12 -06001245 pr_warn_once("Witness protocol support is experimental\n");
Samuel Cabrero0ac4e292020-12-11 22:59:29 -06001246 break;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001247 case Opt_rootfs:
Aurelien Aptelaf3ef3b2021-03-18 19:17:10 +01001248#ifndef CONFIG_CIFS_ROOT
1249 cifs_dbg(VFS, "rootfs support requires CONFIG_CIFS_ROOT config option\n");
1250 goto cifs_parse_mount_err;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001251#endif
Aurelien Aptelaf3ef3b2021-03-18 19:17:10 +01001252 ctx->rootfs = true;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001253 break;
1254 case Opt_posixpaths:
1255 if (result.negated)
1256 ctx->posix_paths = 0;
1257 else
1258 ctx->posix_paths = 1;
1259 break;
1260 case Opt_unix:
Steve French7321be22021-08-23 13:52:12 -05001261 if (result.negated) {
1262 if (ctx->linux_ext == 1)
1263 pr_warn_once("conflicting posix mount options specified\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001264 ctx->linux_ext = 0;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001265 ctx->no_linux_ext = 1;
Steve French7321be22021-08-23 13:52:12 -05001266 } else {
1267 if (ctx->no_linux_ext == 1)
1268 pr_warn_once("conflicting posix mount options specified\n");
1269 ctx->linux_ext = 1;
1270 ctx->no_linux_ext = 0;
1271 }
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001272 break;
1273 case Opt_nocase:
1274 ctx->nocase = 1;
1275 break;
1276 case Opt_brl:
1277 if (result.negated) {
1278 /*
1279 * turn off mandatory locking in mode
1280 * if remote locking is turned off since the
1281 * local vfs will do advisory
1282 */
1283 if (ctx->file_mode ==
1284 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1285 ctx->file_mode = S_IALLUGO;
1286 ctx->nobrl = 1;
1287 } else
1288 ctx->nobrl = 0;
1289 break;
1290 case Opt_handlecache:
1291 if (result.negated)
1292 ctx->nohandlecache = 1;
1293 else
1294 ctx->nohandlecache = 0;
1295 break;
1296 case Opt_forcemandatorylock:
1297 ctx->mand_lock = 1;
1298 break;
1299 case Opt_setuids:
1300 ctx->setuids = result.negated;
1301 break;
1302 case Opt_intr:
1303 ctx->intr = !result.negated;
1304 break;
1305 case Opt_setuidfromacl:
1306 ctx->setuidfromacl = 1;
1307 break;
1308 case Opt_strictsync:
1309 ctx->nostrictsync = result.negated;
1310 break;
1311 case Opt_serverino:
1312 ctx->server_ino = !result.negated;
1313 break;
1314 case Opt_rwpidforward:
1315 ctx->rwpidforward = 1;
1316 break;
1317 case Opt_modesid:
1318 ctx->mode_ace = 1;
1319 break;
1320 case Opt_cifsacl:
1321 ctx->cifs_acl = !result.negated;
1322 break;
1323 case Opt_acl:
1324 ctx->no_psx_acl = result.negated;
1325 break;
1326 case Opt_locallease:
1327 ctx->local_lease = 1;
1328 break;
1329 case Opt_sign:
1330 ctx->sign = true;
1331 break;
1332 case Opt_ignore_signature:
1333 ctx->sign = true;
1334 ctx->ignore_signature = true;
1335 break;
1336 case Opt_seal:
1337 /* we do not do the following in secFlags because seal
1338 * is a per tree connection (mount) not a per socket
1339 * or per-smb connection option in the protocol
1340 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1341 */
1342 ctx->seal = 1;
1343 break;
1344 case Opt_noac:
1345 pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1346 break;
1347 case Opt_fsc:
1348#ifndef CONFIG_CIFS_FSCACHE
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001349 cifs_errorf(fc, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001350 goto cifs_parse_mount_err;
1351#endif
1352 ctx->fsc = true;
1353 break;
1354 case Opt_mfsymlinks:
1355 ctx->mfsymlinks = true;
1356 break;
1357 case Opt_multiuser:
1358 ctx->multiuser = true;
1359 break;
1360 case Opt_sloppy:
1361 ctx->sloppy = true;
1362 break;
1363 case Opt_nosharesock:
1364 ctx->nosharesock = true;
1365 break;
1366 case Opt_persistent:
1367 if (result.negated) {
Steve French27cf9482020-12-16 01:22:54 -06001368 ctx->nopersistent = true;
1369 if (ctx->persistent) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001370 cifs_errorf(fc, "persistenthandles mount options conflict\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001371 goto cifs_parse_mount_err;
1372 }
1373 } else {
Steve French27cf9482020-12-16 01:22:54 -06001374 ctx->persistent = true;
1375 if ((ctx->nopersistent) || (ctx->resilient)) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001376 cifs_errorf(fc, "persistenthandles mount options conflict\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001377 goto cifs_parse_mount_err;
1378 }
1379 }
1380 break;
1381 case Opt_resilient:
1382 if (result.negated) {
1383 ctx->resilient = false; /* already the default */
1384 } else {
1385 ctx->resilient = true;
1386 if (ctx->persistent) {
Aurelien Aptel24feddd2021-03-01 19:34:02 +01001387 cifs_errorf(fc, "persistenthandles mount options conflict\n");
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001388 goto cifs_parse_mount_err;
1389 }
1390 }
1391 break;
1392 case Opt_domainauto:
1393 ctx->domainauto = true;
1394 break;
1395 case Opt_rdma:
1396 ctx->rdma = true;
1397 break;
1398 }
Steve French31f65512020-12-16 16:26:35 -06001399 /* case Opt_ignore: - is ignored as expected ... */
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001400
1401 return 0;
1402
1403 cifs_parse_mount_err:
Steve Frenchbd2f0b42021-01-28 16:43:03 -06001404 return -EINVAL;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001405}
1406
1407int smb3_init_fs_context(struct fs_context *fc)
1408{
1409 struct smb3_fs_context *ctx;
1410 char *nodename = utsname()->nodename;
1411 int i;
1412
1413 ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
1414 if (unlikely(!ctx))
1415 return -ENOMEM;
1416
1417 /*
1418 * does not have to be perfect mapping since field is
1419 * informational, only used for servers that do not support
1420 * port 445 and it can be overridden at mount time
1421 */
1422 memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1423 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
1424 ctx->source_rfc1001_name[i] = toupper(nodename[i]);
1425
1426 ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1427 /*
1428 * null target name indicates to use *SMBSERVR default called name
1429 * if we end up sending RFC1001 session initialize
1430 */
1431 ctx->target_rfc1001_name[0] = 0;
1432 ctx->cred_uid = current_uid();
1433 ctx->linux_uid = current_uid();
1434 ctx->linux_gid = current_gid();
Steve Frenchb8d64f82021-04-24 21:46:23 -05001435 /* By default 4MB read ahead size, 1MB block size */
1436 ctx->bsize = CIFS_DEFAULT_IOSIZE; /* can improve cp performance significantly */
1437 ctx->rasize = 0; /* 0 = use default (ie negotiated rsize) for read ahead pages */
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001438
1439 /*
1440 * default to SFM style remapping of seven reserved characters
1441 * unless user overrides it or we negotiate CIFS POSIX where
1442 * it is unnecessary. Can not simultaneously use more than one mapping
1443 * since then readdir could list files that open could not open
1444 */
1445 ctx->remap = true;
1446
1447 /* default to only allowing write access to owner of the mount */
1448 ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1449
1450 /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1451 /* default is always to request posix paths. */
1452 ctx->posix_paths = 1;
1453 /* default to using server inode numbers where available */
1454 ctx->server_ino = 1;
1455
1456 /* default is to use strict cifs caching semantics */
1457 ctx->strict_io = true;
1458
Steve French57804642021-02-24 12:12:53 -06001459 ctx->acregmax = CIFS_DEF_ACTIMEO;
Steve French4c9f9482021-02-23 15:50:57 -06001460 ctx->acdirmax = CIFS_DEF_ACTIMEO;
Ronnie Sahlberg24e0a1e2020-12-10 00:06:02 -06001461
1462 /* Most clients set timeout to 0, allows server to use its default */
1463 ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1464
1465 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1466 ctx->ops = &smb30_operations;
1467 ctx->vals = &smbdefault_values;
1468
1469 ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1470
1471 /* default to no multichannel (single server connection) */
1472 ctx->multichannel = false;
1473 ctx->max_channels = 1;
1474
1475 ctx->backupuid_specified = false; /* no backup intent for a user */
1476 ctx->backupgid_specified = false; /* no backup intent for a group */
1477
1478/*
1479 * short int override_uid = -1;
1480 * short int override_gid = -1;
1481 * char *nodename = strdup(utsname()->nodename);
1482 * struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
1483 */
1484
1485 fc->fs_private = ctx;
1486 fc->ops = &smb3_fs_context_ops;
1487 return 0;
1488}
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001489
1490void
1491smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
1492{
1493 if (ctx == NULL)
1494 return;
1495
1496 /*
1497 * Make sure this stays in sync with smb3_fs_context_dup()
1498 */
1499 kfree(ctx->mount_options);
1500 ctx->mount_options = NULL;
1501 kfree(ctx->username);
1502 ctx->username = NULL;
1503 kfree_sensitive(ctx->password);
1504 ctx->password = NULL;
Shyam Prasad N7be32482021-10-14 11:52:39 +00001505 kfree(ctx->server_hostname);
1506 ctx->server_hostname = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001507 kfree(ctx->UNC);
1508 ctx->UNC = NULL;
Ronnie Sahlbergaf1a3d22021-02-11 16:06:16 +10001509 kfree(ctx->source);
1510 ctx->source = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001511 kfree(ctx->domainname);
1512 ctx->domainname = NULL;
1513 kfree(ctx->nodename);
1514 ctx->nodename = NULL;
1515 kfree(ctx->iocharset);
1516 ctx->iocharset = NULL;
1517 kfree(ctx->prepath);
1518 ctx->prepath = NULL;
Ronnie Sahlbergc741cba2020-12-14 16:40:16 +10001519}
1520
1521void
1522smb3_cleanup_fs_context(struct smb3_fs_context *ctx)
1523{
1524 if (!ctx)
1525 return;
1526 smb3_cleanup_fs_context_contents(ctx);
1527 kfree(ctx);
1528}
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001529
1530void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
1531{
1532 struct smb3_fs_context *ctx = cifs_sb->ctx;
1533
1534 if (ctx->nodfs)
1535 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
1536 else
1537 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS;
1538
1539 if (ctx->noperm)
1540 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1541 else
1542 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM;
1543
1544 if (ctx->setuids)
1545 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1546 else
1547 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID;
1548
1549 if (ctx->setuidfromacl)
1550 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
1551 else
1552 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL;
1553
1554 if (ctx->server_ino)
1555 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1556 else
1557 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
1558
1559 if (ctx->remap)
1560 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
1561 else
1562 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR;
1563
1564 if (ctx->sfu_remap)
1565 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1566 else
1567 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
1568
1569 if (ctx->no_xattr)
1570 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1571 else
1572 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR;
1573
1574 if (ctx->sfu_emul)
1575 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1576 else
1577 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL;
1578
1579 if (ctx->nobrl)
1580 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1581 else
1582 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL;
1583
1584 if (ctx->nohandlecache)
1585 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
1586 else
1587 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
1588
1589 if (ctx->nostrictsync)
1590 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
1591 else
1592 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC;
1593
1594 if (ctx->mand_lock)
1595 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
1596 else
1597 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL;
1598
1599 if (ctx->rwpidforward)
1600 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
1601 else
1602 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD;
1603
1604 if (ctx->mode_ace)
1605 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
1606 else
1607 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID;
1608
1609 if (ctx->cifs_acl)
1610 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1611 else
1612 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL;
1613
1614 if (ctx->backupuid_specified)
1615 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
1616 else
1617 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
1618
1619 if (ctx->backupgid_specified)
1620 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
1621 else
1622 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
1623
1624 if (ctx->override_uid)
1625 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
1626 else
1627 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID;
1628
1629 if (ctx->override_gid)
1630 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
1631 else
1632 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID;
1633
1634 if (ctx->dynperm)
1635 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
1636 else
1637 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM;
1638
1639 if (ctx->fsc)
1640 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
1641 else
1642 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE;
1643
1644 if (ctx->multiuser)
1645 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
1646 CIFS_MOUNT_NO_PERM);
1647 else
Ronnie Sahlberga0f85e32021-02-10 11:55:47 +10001648 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MULTIUSER;
1649
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001650
1651 if (ctx->strict_io)
1652 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
1653 else
1654 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO;
1655
1656 if (ctx->direct_io)
1657 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1658 else
1659 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO;
1660
1661 if (ctx->mfsymlinks)
1662 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
1663 else
1664 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS;
1665 if (ctx->mfsymlinks) {
1666 if (ctx->sfu_emul) {
1667 /*
1668 * Our SFU ("Services for Unix" emulation does not allow
1669 * creating symlinks but does allow reading existing SFU
1670 * symlinks (it does allow both creating and reading SFU
1671 * style mknod and FIFOs though). When "mfsymlinks" and
1672 * "sfu" are both enabled at the same time, it allows
1673 * reading both types of symlinks, but will only create
1674 * them with mfsymlinks format. This allows better
1675 * Apple compatibility (probably better for Samba too)
1676 * while still recognizing old Windows style symlinks.
1677 */
1678 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
1679 }
1680 }
Steve French087f7572021-04-29 00:18:43 -05001681 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SHUTDOWN;
Ronnie Sahlberg2d39f502020-12-14 16:40:25 +10001682
1683 return;
1684}