brintos

brintos / linux-shallow public Read only

0
0
Text · 51.1 KiB · 5c5a520 Raw
1929 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *   Copyright (C) 2020, Microsoft Corporation.4 *5 *   Author(s): Steve French <stfrench@microsoft.com>6 *              David Howells <dhowells@redhat.com>7 */8 9/*10#include <linux/module.h>11#include <linux/nsproxy.h>12#include <linux/slab.h>13#include <linux/magic.h>14#include <linux/security.h>15#include <net/net_namespace.h>16#ifdef CONFIG_CIFS_DFS_UPCALL17#include "dfs_cache.h"18#endif19*/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"30#include "cifsglob.h"31#include "cifsproto.h"32#include "cifs_unicode.h"33#include "cifs_debug.h"34#include "cifs_fs_sb.h"35#include "ntlmssp.h"36#include "nterr.h"37#include "rfc1002pdu.h"38#include "fs_context.h"39 40DEFINE_MUTEX(cifs_mount_mutex);41 42static 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 56static 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" },62	{ Opt_sec_ntlmv2, "nontlm" },63	{ Opt_sec_ntlmv2, "ntlmv2" },64	{ Opt_sec_ntlmv2i, "ntlmv2i" },65	{ Opt_sec_none, "none" },66 67	{ Opt_sec_err, NULL }68};69 70const 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),99	fsparam_flag("idsfromsid", Opt_setuidfromacl),100	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),111	fsparam_flag("signloosely", Opt_ignore_signature),112	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),119	fsparam_flag_no("persistenthandles", Opt_persistent),120	fsparam_flag_no("resilienthandles", Opt_resilient),121	fsparam_flag_no("tcpnodelay", Opt_tcp_nodelay),122	fsparam_flag("nosparse", Opt_nosparse),123	fsparam_flag("domainauto", Opt_domainauto),124	fsparam_flag("rdma", Opt_rdma),125	fsparam_flag("modesid", Opt_modesid),126	fsparam_flag("modefromsid", Opt_modesid),127	fsparam_flag("rootfs", Opt_rootfs),128	fsparam_flag("compress", Opt_compress),129	fsparam_flag("witness", Opt_witness),130 131	/* Mount options which take uid or gid */132	fsparam_uid("backupuid", Opt_backupuid),133	fsparam_gid("backupgid", Opt_backupgid),134	fsparam_uid("uid", Opt_uid),135	fsparam_uid("cruid", Opt_cruid),136	fsparam_gid("gid", Opt_gid),137 138	/* Mount options which take numeric value */139	fsparam_u32("file_mode", Opt_file_mode),140	fsparam_u32("dirmode", Opt_dirmode),141	fsparam_u32("dir_mode", Opt_dirmode),142	fsparam_u32("port", Opt_port),143	fsparam_u32("min_enc_offload", Opt_min_enc_offload),144	fsparam_u32("retrans", Opt_retrans),145	fsparam_u32("esize", Opt_min_enc_offload),146	fsparam_u32("bsize", Opt_blocksize),147	fsparam_u32("rasize", Opt_rasize),148	fsparam_u32("rsize", Opt_rsize),149	fsparam_u32("wsize", Opt_wsize),150	fsparam_u32("actimeo", Opt_actimeo),151	fsparam_u32("acdirmax", Opt_acdirmax),152	fsparam_u32("acregmax", Opt_acregmax),153	fsparam_u32("closetimeo", Opt_closetimeo),154	fsparam_u32("echo_interval", Opt_echo_interval),155	fsparam_u32("max_credits", Opt_max_credits),156	fsparam_u32("max_cached_dirs", Opt_max_cached_dirs),157	fsparam_u32("handletimeout", Opt_handletimeout),158	fsparam_u64("snapshot", Opt_snapshot),159	fsparam_u32("max_channels", Opt_max_channels),160 161	/* Mount options which take string value */162	fsparam_string("source", Opt_source),163	fsparam_string("user", Opt_user),164	fsparam_string("username", Opt_user),165	fsparam_string("pass", Opt_pass),166	fsparam_string("password", Opt_pass),167	fsparam_string("password2", Opt_pass2),168	fsparam_string("ip", Opt_ip),169	fsparam_string("addr", Opt_ip),170	fsparam_string("domain", Opt_domain),171	fsparam_string("dom", Opt_domain),172	fsparam_string("srcaddr", Opt_srcaddr),173	fsparam_string("iocharset", Opt_iocharset),174	fsparam_string("netbiosname", Opt_netbiosname),175	fsparam_string("servern", Opt_servern),176	fsparam_string("ver", Opt_ver),177	fsparam_string("vers", Opt_vers),178	fsparam_string("sec", Opt_sec),179	fsparam_string("cache", Opt_cache),180	fsparam_string("reparse", Opt_reparse),181 182	/* Arguments that should be ignored */183	fsparam_flag("guest", Opt_ignore),184	fsparam_flag("noatime", Opt_ignore),185	fsparam_flag("relatime", Opt_ignore),186	fsparam_flag("_netdev", Opt_ignore),187	fsparam_flag_no("suid", Opt_ignore),188	fsparam_flag_no("exec", Opt_ignore),189	fsparam_flag_no("dev", Opt_ignore),190	fsparam_flag_no("mand", Opt_ignore),191	fsparam_flag_no("auto", Opt_ignore),192	fsparam_string("cred", Opt_ignore),193	fsparam_string("credentials", Opt_ignore),194	/*195	 * UNC and prefixpath is now extracted from Opt_source196	 * in the new mount API so we can just ignore them going forward.197	 */198	fsparam_string("unc", Opt_ignore),199	fsparam_string("prefixpath", Opt_ignore),200	{}201};202 203static int204cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)205{206 207	substring_t args[MAX_OPT_ARGS];208 209	/*210	 * With mount options, the last one should win. Reset any existing211	 * settings back to default.212	 */213	ctx->sectype = Unspecified;214	ctx->sign = false;215 216	switch (match_token(value, cifs_secflavor_tokens, args)) {217	case Opt_sec_krb5p:218		cifs_errorf(fc, "sec=krb5p is not supported. Use sec=krb5,seal instead\n");219		return 1;220	case Opt_sec_krb5i:221		ctx->sign = true;222		fallthrough;223	case Opt_sec_krb5:224		ctx->sectype = Kerberos;225		break;226	case Opt_sec_ntlmsspi:227		ctx->sign = true;228		fallthrough;229	case Opt_sec_ntlmssp:230		ctx->sectype = RawNTLMSSP;231		break;232	case Opt_sec_ntlmv2i:233		ctx->sign = true;234		fallthrough;235	case Opt_sec_ntlmv2:236		ctx->sectype = NTLMv2;237		break;238	case Opt_sec_none:239		ctx->nullauth = 1;240		kfree(ctx->username);241		ctx->username = NULL;242		break;243	default:244		cifs_errorf(fc, "bad security option: %s\n", value);245		return 1;246	}247 248	return 0;249}250 251static const match_table_t cifs_cacheflavor_tokens = {252	{ Opt_cache_loose, "loose" },253	{ Opt_cache_strict, "strict" },254	{ Opt_cache_none, "none" },255	{ Opt_cache_ro, "ro" },256	{ Opt_cache_rw, "singleclient" },257	{ Opt_cache_err, NULL }258};259 260static int261cifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)262{263	substring_t args[MAX_OPT_ARGS];264 265	switch (match_token(value, cifs_cacheflavor_tokens, args)) {266	case Opt_cache_loose:267		ctx->direct_io = false;268		ctx->strict_io = false;269		ctx->cache_ro = false;270		ctx->cache_rw = false;271		break;272	case Opt_cache_strict:273		ctx->direct_io = false;274		ctx->strict_io = true;275		ctx->cache_ro = false;276		ctx->cache_rw = false;277		break;278	case Opt_cache_none:279		ctx->direct_io = true;280		ctx->strict_io = false;281		ctx->cache_ro = false;282		ctx->cache_rw = false;283		break;284	case Opt_cache_ro:285		ctx->direct_io = false;286		ctx->strict_io = false;287		ctx->cache_ro = true;288		ctx->cache_rw = false;289		break;290	case Opt_cache_rw:291		ctx->direct_io = false;292		ctx->strict_io = false;293		ctx->cache_ro = false;294		ctx->cache_rw = true;295		break;296	default:297		cifs_errorf(fc, "bad cache= option: %s\n", value);298		return 1;299	}300	return 0;301}302 303static const match_table_t reparse_flavor_tokens = {304	{ Opt_reparse_default,	"default" },305	{ Opt_reparse_nfs,	"nfs" },306	{ Opt_reparse_wsl,	"wsl" },307	{ Opt_reparse_err,	NULL },308};309 310static int parse_reparse_flavor(struct fs_context *fc, char *value,311				struct smb3_fs_context *ctx)312{313	substring_t args[MAX_OPT_ARGS];314 315	switch (match_token(value, reparse_flavor_tokens, args)) {316	case Opt_reparse_default:317		ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;318		break;319	case Opt_reparse_nfs:320		ctx->reparse_type = CIFS_REPARSE_TYPE_NFS;321		break;322	case Opt_reparse_wsl:323		ctx->reparse_type = CIFS_REPARSE_TYPE_WSL;324		break;325	default:326		cifs_errorf(fc, "bad reparse= option: %s\n", value);327		return 1;328	}329	return 0;330}331 332#define DUP_CTX_STR(field)						\333do {									\334	if (ctx->field) {						\335		new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC);	\336		if (new_ctx->field == NULL) {				\337			smb3_cleanup_fs_context_contents(new_ctx);	\338			return -ENOMEM;					\339		}							\340	}								\341} while (0)342 343int344smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)345{346	memcpy(new_ctx, ctx, sizeof(*ctx));347	new_ctx->prepath = NULL;348	new_ctx->nodename = NULL;349	new_ctx->username = NULL;350	new_ctx->password = NULL;351	new_ctx->password2 = NULL;352	new_ctx->server_hostname = NULL;353	new_ctx->domainname = NULL;354	new_ctx->UNC = NULL;355	new_ctx->source = NULL;356	new_ctx->iocharset = NULL;357	new_ctx->leaf_fullpath = NULL;358	/*359	 * Make sure to stay in sync with smb3_cleanup_fs_context_contents()360	 */361	DUP_CTX_STR(prepath);362	DUP_CTX_STR(username);363	DUP_CTX_STR(password);364	DUP_CTX_STR(password2);365	DUP_CTX_STR(server_hostname);366	DUP_CTX_STR(UNC);367	DUP_CTX_STR(source);368	DUP_CTX_STR(domainname);369	DUP_CTX_STR(nodename);370	DUP_CTX_STR(iocharset);371	DUP_CTX_STR(leaf_fullpath);372 373	return 0;374}375 376static int377cifs_parse_smb_version(struct fs_context *fc, char *value, struct smb3_fs_context *ctx, bool is_smb3)378{379	substring_t args[MAX_OPT_ARGS];380 381	switch (match_token(value, cifs_smb_version_tokens, args)) {382#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY383	case Smb_1:384		if (disable_legacy_dialects) {385			cifs_errorf(fc, "mount with legacy dialect disabled\n");386			return 1;387		}388		if (is_smb3) {389			cifs_errorf(fc, "vers=1.0 (cifs) not permitted when mounting with smb3\n");390			return 1;391		}392		cifs_errorf(fc, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");393		ctx->ops = &smb1_operations;394		ctx->vals = &smb1_values;395		break;396	case Smb_20:397		if (disable_legacy_dialects) {398			cifs_errorf(fc, "mount with legacy dialect disabled\n");399			return 1;400		}401		if (is_smb3) {402			cifs_errorf(fc, "vers=2.0 not permitted when mounting with smb3\n");403			return 1;404		}405		ctx->ops = &smb20_operations;406		ctx->vals = &smb20_values;407		break;408#else409	case Smb_1:410		cifs_errorf(fc, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");411		return 1;412	case Smb_20:413		cifs_errorf(fc, "vers=2.0 mount not permitted when legacy dialects disabled\n");414		return 1;415#endif /* CIFS_ALLOW_INSECURE_LEGACY */416	case Smb_21:417		ctx->ops = &smb21_operations;418		ctx->vals = &smb21_values;419		break;420	case Smb_30:421		ctx->ops = &smb30_operations;422		ctx->vals = &smb30_values;423		break;424	case Smb_302:425		ctx->ops = &smb30_operations; /* currently identical with 3.0 */426		ctx->vals = &smb302_values;427		break;428	case Smb_311:429		ctx->ops = &smb311_operations;430		ctx->vals = &smb311_values;431		break;432	case Smb_3any:433		ctx->ops = &smb30_operations; /* currently identical with 3.0 */434		ctx->vals = &smb3any_values;435		break;436	case Smb_default:437		ctx->ops = &smb30_operations;438		ctx->vals = &smbdefault_values;439		break;440	default:441		cifs_errorf(fc, "Unknown vers= option specified: %s\n", value);442		return 1;443	}444	return 0;445}446 447int smb3_parse_opt(const char *options, const char *key, char **val)448{449	int rc = -ENOENT;450	char *opts, *orig, *p;451 452	orig = opts = kstrdup(options, GFP_KERNEL);453	if (!opts)454		return -ENOMEM;455 456	while ((p = strsep(&opts, ","))) {457		char *nval;458 459		if (!*p)460			continue;461		if (strncasecmp(p, key, strlen(key)))462			continue;463		nval = strchr(p, '=');464		if (nval) {465			if (nval == p)466				continue;467			*nval++ = 0;468			*val = kstrdup(nval, GFP_KERNEL);469			rc = !*val ? -ENOMEM : 0;470			goto out;471		}472	}473out:474	kfree(orig);475	return rc;476}477 478/*479 * Remove duplicate path delimiters. Windows is supposed to do that480 * but there are some bugs that prevent rename from working if there are481 * multiple delimiters.482 *483 * Return a sanitized duplicate of @path or NULL for empty prefix paths.484 * Otherwise, return ERR_PTR.485 *486 * @gfp indicates the GFP_* flags for kstrdup.487 * The caller is responsible for freeing the original.488 */489#define IS_DELIM(c) ((c) == '/' || (c) == '\\')490char *cifs_sanitize_prepath(char *prepath, gfp_t gfp)491{492	char *cursor1 = prepath, *cursor2 = prepath;493	char *s;494 495	/* skip all prepended delimiters */496	while (IS_DELIM(*cursor1))497		cursor1++;498 499	/* copy the first letter */500	*cursor2 = *cursor1;501 502	/* copy the remainder... */503	while (*(cursor1++)) {504		/* ... skipping all duplicated delimiters */505		if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2))506			continue;507		*(++cursor2) = *cursor1;508	}509 510	/* if the last character is a delimiter, skip it */511	if (IS_DELIM(*(cursor2 - 1)))512		cursor2--;513 514	*cursor2 = '\0';515	if (!*prepath)516		return NULL;517	s = kstrdup(prepath, gfp);518	if (!s)519		return ERR_PTR(-ENOMEM);520	return s;521}522 523/*524 * Return full path based on the values of @ctx->{UNC,prepath}.525 *526 * It is assumed that both values were already parsed by smb3_parse_devname().527 */528char *smb3_fs_context_fullpath(const struct smb3_fs_context *ctx, char dirsep)529{530	size_t ulen, plen;531	char *s;532 533	ulen = strlen(ctx->UNC);534	plen = ctx->prepath ? strlen(ctx->prepath) + 1 : 0;535 536	s = kmalloc(ulen + plen + 1, GFP_KERNEL);537	if (!s)538		return ERR_PTR(-ENOMEM);539	memcpy(s, ctx->UNC, ulen);540	if (plen) {541		s[ulen] = dirsep;542		memcpy(s + ulen + 1, ctx->prepath, plen);543	}544	s[ulen + plen] = '\0';545	convert_delimiter(s, dirsep);546	return s;547}548 549/*550 * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath551 * fields with the result. Returns 0 on success and an error otherwise552 * (e.g. ENOMEM or EINVAL)553 */554int555smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)556{557	char *pos;558	const char *delims = "/\\";559	size_t len;560	int rc;561 562	if (unlikely(!devname || !*devname)) {563		cifs_dbg(VFS, "Device name not specified\n");564		return -EINVAL;565	}566 567	/* make sure we have a valid UNC double delimiter prefix */568	len = strspn(devname, delims);569	if (len != 2)570		return -EINVAL;571 572	/* find delimiter between host and sharename */573	pos = strpbrk(devname + 2, delims);574	if (!pos)575		return -EINVAL;576 577	/* record the server hostname */578	kfree(ctx->server_hostname);579	ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL);580	if (!ctx->server_hostname)581		return -ENOMEM;582 583	/* skip past delimiter */584	++pos;585 586	/* now go until next delimiter or end of string */587	len = strcspn(pos, delims);588	if (!len)589		return -EINVAL;590 591	/* move "pos" up to delimiter or NULL */592	pos += len;593	kfree(ctx->UNC);594	ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);595	if (!ctx->UNC)596		return -ENOMEM;597 598	convert_delimiter(ctx->UNC, '\\');599 600	/* skip any delimiter */601	if (*pos == '/' || *pos == '\\')602		pos++;603 604	kfree(ctx->prepath);605	ctx->prepath = NULL;606 607	/* If pos is NULL then no prepath */608	if (!*pos)609		return 0;610 611	ctx->prepath = cifs_sanitize_prepath(pos, GFP_KERNEL);612	if (IS_ERR(ctx->prepath)) {613		rc = PTR_ERR(ctx->prepath);614		ctx->prepath = NULL;615		return rc;616	}617 618	return 0;619}620 621static void smb3_fs_context_free(struct fs_context *fc);622static int smb3_fs_context_parse_param(struct fs_context *fc,623				       struct fs_parameter *param);624static int smb3_fs_context_parse_monolithic(struct fs_context *fc,625					    void *data);626static int smb3_get_tree(struct fs_context *fc);627static int smb3_reconfigure(struct fs_context *fc);628 629static const struct fs_context_operations smb3_fs_context_ops = {630	.free			= smb3_fs_context_free,631	.parse_param		= smb3_fs_context_parse_param,632	.parse_monolithic	= smb3_fs_context_parse_monolithic,633	.get_tree		= smb3_get_tree,634	.reconfigure		= smb3_reconfigure,635};636 637/*638 * Parse a monolithic block of data from sys_mount().639 * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data640 * @ctx: The superblock configuration to fill in.641 * @data: The data to parse642 *643 * Parse a blob of data that's in key[=val][,key[=val]]* form.  This can be644 * called from the ->monolithic_mount_data() fs_context operation.645 *646 * Returns 0 on success or the error returned by the ->parse_option() fs_context647 * operation on failure.648 */649static int smb3_fs_context_parse_monolithic(struct fs_context *fc,650					   void *data)651{652	char *options = data, *key;653	int ret = 0;654 655	if (!options)656		return 0;657 658	ret = security_sb_eat_lsm_opts(options, &fc->security);659	if (ret)660		return ret;661 662	/* BB Need to add support for sep= here TBD */663	while ((key = strsep(&options, ",")) != NULL) {664		size_t len;665		char *value;666 667		if (*key == 0)668			break;669 670		/* Check if following character is the deliminator If yes,671		 * we have encountered a double deliminator reset the NULL672		 * character to the deliminator673		 */674		while (options && options[0] == ',') {675			len = strlen(key);676			strcpy(key + len, options);677			options = strchr(options, ',');678			if (options)679				*options++ = 0;680		}681 682 683		len = 0;684		value = strchr(key, '=');685		if (value) {686			if (value == key)687				continue;688			*value++ = 0;689			len = strlen(value);690		}691 692		ret = vfs_parse_fs_string(fc, key, value, len);693		if (ret < 0)694			break;695	}696 697	return ret;698}699 700/*701 * Validate the preparsed information in the config.702 */703static int smb3_fs_context_validate(struct fs_context *fc)704{705	struct smb3_fs_context *ctx = smb3_fc2context(fc);706 707	if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {708		cifs_errorf(fc, "SMB Direct requires Version >=3.0\n");709		return -EOPNOTSUPP;710	}711 712#ifndef CONFIG_KEYS713	/* Muliuser mounts require CONFIG_KEYS support */714	if (ctx->multiuser) {715		cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");716		return -1;717	}718#endif719 720	if (ctx->got_version == false)721		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");722 723 724	if (!ctx->UNC) {725		cifs_errorf(fc, "CIFS mount error: No usable UNC path provided in device string!\n");726		return -1;727	}728 729	/* make sure UNC has a share name */730	if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {731		cifs_errorf(fc, "Malformed UNC. Unable to find share name.\n");732		return -ENOENT;733	}734 735	if (!ctx->got_ip) {736		int len;737		const char *slash;738 739		/* No ip= option specified? Try to get it from UNC */740		/* Use the address part of the UNC. */741		slash = strchr(&ctx->UNC[2], '\\');742		len = slash - &ctx->UNC[2];743		if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,744					  &ctx->UNC[2], len)) {745			pr_err("Unable to determine destination address\n");746			return -EHOSTUNREACH;747		}748	}749 750	/* set the port that we got earlier */751	cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);752 753	if (ctx->uid_specified && !ctx->forceuid_specified) {754		ctx->override_uid = 1;755		pr_notice("enabling forceuid mount option implicitly because uid= option is specified\n");756	}757 758	if (ctx->gid_specified && !ctx->forcegid_specified) {759		ctx->override_gid = 1;760		pr_notice("enabling forcegid mount option implicitly because gid= option is specified\n");761	}762 763	if (ctx->override_uid && !ctx->uid_specified) {764		ctx->override_uid = 0;765		pr_notice("ignoring forceuid mount option specified with no uid= option\n");766	}767 768	if (ctx->override_gid && !ctx->gid_specified) {769		ctx->override_gid = 0;770		pr_notice("ignoring forcegid mount option specified with no gid= option\n");771	}772 773	return 0;774}775 776static int smb3_get_tree_common(struct fs_context *fc)777{778	struct smb3_fs_context *ctx = smb3_fc2context(fc);779	struct dentry *root;780	int rc = 0;781 782	root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);783	if (IS_ERR(root))784		return PTR_ERR(root);785 786	fc->root = root;787 788	return rc;789}790 791/*792 * Create an SMB3 superblock from the parameters passed.793 */794static int smb3_get_tree(struct fs_context *fc)795{796	int err = smb3_fs_context_validate(fc);797	int ret;798 799	if (err)800		return err;801	cifs_mount_lock();802	ret = smb3_get_tree_common(fc);803	cifs_mount_unlock();804	return ret;805}806 807static void smb3_fs_context_free(struct fs_context *fc)808{809	struct smb3_fs_context *ctx = smb3_fc2context(fc);810 811	smb3_cleanup_fs_context(ctx);812}813 814/*815 * Compare the old and new proposed context during reconfigure816 * and check if the changes are compatible.817 */818static int smb3_verify_reconfigure_ctx(struct fs_context *fc,819				       struct smb3_fs_context *new_ctx,820				       struct smb3_fs_context *old_ctx, bool need_recon)821{822	if (new_ctx->posix_paths != old_ctx->posix_paths) {823		cifs_errorf(fc, "can not change posixpaths during remount\n");824		return -EINVAL;825	}826	if (new_ctx->sectype != old_ctx->sectype) {827		cifs_errorf(fc, "can not change sec during remount\n");828		return -EINVAL;829	}830	if (new_ctx->multiuser != old_ctx->multiuser) {831		cifs_errorf(fc, "can not change multiuser during remount\n");832		return -EINVAL;833	}834	if (new_ctx->UNC &&835	    (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {836		cifs_errorf(fc, "can not change UNC during remount\n");837		return -EINVAL;838	}839	if (new_ctx->username &&840	    (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {841		cifs_errorf(fc, "can not change username during remount\n");842		return -EINVAL;843	}844	if (new_ctx->password &&845	    (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {846		if (need_recon == false) {847			cifs_errorf(fc,848				    "can not change password of active session during remount\n");849			return -EINVAL;850		} else if (old_ctx->sectype == Kerberos) {851			cifs_errorf(fc,852				    "can not change password for Kerberos via remount\n");853			return -EINVAL;854		}855	}856	if (new_ctx->domainname &&857	    (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {858		cifs_errorf(fc, "can not change domainname during remount\n");859		return -EINVAL;860	}861	if (strcmp(new_ctx->workstation_name, old_ctx->workstation_name)) {862		cifs_errorf(fc, "can not change workstation_name during remount\n");863		return -EINVAL;864	}865	if (new_ctx->nodename &&866	    (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {867		cifs_errorf(fc, "can not change nodename during remount\n");868		return -EINVAL;869	}870	if (new_ctx->iocharset &&871	    (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {872		cifs_errorf(fc, "can not change iocharset during remount\n");873		return -EINVAL;874	}875 876	return 0;877}878 879#define STEAL_STRING(cifs_sb, ctx, field)				\880do {									\881	kfree(ctx->field);						\882	ctx->field = cifs_sb->ctx->field;				\883	cifs_sb->ctx->field = NULL;					\884} while (0)885 886#define STEAL_STRING_SENSITIVE(cifs_sb, ctx, field)			\887do {									\888	kfree_sensitive(ctx->field);					\889	ctx->field = cifs_sb->ctx->field;				\890	cifs_sb->ctx->field = NULL;					\891} while (0)892 893static int smb3_reconfigure(struct fs_context *fc)894{895	struct smb3_fs_context *ctx = smb3_fc2context(fc);896	struct dentry *root = fc->root;897	struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);898	struct cifs_ses *ses = cifs_sb_master_tcon(cifs_sb)->ses;899	bool need_recon = false;900	int rc;901 902	if (ses->expired_pwd)903		need_recon = true;904 905	rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx, need_recon);906	if (rc)907		return rc;908 909	/*910	 * We can not change UNC/username/password/domainname/911	 * workstation_name/nodename/iocharset912	 * during reconnect so ignore what we have in the new context and913	 * just use what we already have in cifs_sb->ctx.914	 */915	STEAL_STRING(cifs_sb, ctx, UNC);916	STEAL_STRING(cifs_sb, ctx, source);917	STEAL_STRING(cifs_sb, ctx, username);918	if (need_recon == false)919		STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);920	else  {921		kfree_sensitive(ses->password);922		ses->password = kstrdup(ctx->password, GFP_KERNEL);923		if (!ses->password)924			return -ENOMEM;925		kfree_sensitive(ses->password2);926		ses->password2 = kstrdup(ctx->password2, GFP_KERNEL);927		if (!ses->password2) {928			kfree_sensitive(ses->password);929			ses->password = NULL;930			return -ENOMEM;931		}932	}933	STEAL_STRING(cifs_sb, ctx, domainname);934	STEAL_STRING(cifs_sb, ctx, nodename);935	STEAL_STRING(cifs_sb, ctx, iocharset);936 937	/* if rsize or wsize not passed in on remount, use previous values */938	if (ctx->rsize == 0)939		ctx->rsize = cifs_sb->ctx->rsize;940	if (ctx->wsize == 0)941		ctx->wsize = cifs_sb->ctx->wsize;942 943 944	smb3_cleanup_fs_context_contents(cifs_sb->ctx);945	rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);946	smb3_update_mnt_flags(cifs_sb);947#ifdef CONFIG_CIFS_DFS_UPCALL948	if (!rc)949		rc = dfs_cache_remount_fs(cifs_sb);950#endif951 952	return rc;953}954 955static int smb3_fs_context_parse_param(struct fs_context *fc,956				      struct fs_parameter *param)957{958	struct fs_parse_result result;959	struct smb3_fs_context *ctx = smb3_fc2context(fc);960	int i, opt;961	bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");962	bool skip_parsing = false;963 964	cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);965 966	/*967	 * fs_parse can not handle string options with an empty value so968	 * we will need special handling of them.969	 */970	if (param->type == fs_value_is_string && param->string[0] == 0) {971		if (!strcmp("pass", param->key) || !strcmp("password", param->key)) {972			skip_parsing = true;973			opt = Opt_pass;974		} else if (!strcmp("user", param->key) || !strcmp("username", param->key)) {975			skip_parsing = true;976			opt = Opt_user;977		}978	}979 980	if (!skip_parsing) {981		opt = fs_parse(fc, smb3_fs_parameters, param, &result);982		if (opt < 0)983			return ctx->sloppy ? 1 : opt;984	}985 986	switch (opt) {987	case Opt_compress:988		if (!IS_ENABLED(CONFIG_CIFS_COMPRESSION)) {989			cifs_errorf(fc, "CONFIG_CIFS_COMPRESSION kernel config option is unset\n");990			goto cifs_parse_mount_err;991		}992		ctx->compress = true;993		cifs_dbg(VFS, "SMB3 compression support is experimental\n");994		break;995	case Opt_nodfs:996		ctx->nodfs = 1;997		break;998	case Opt_hard:999		if (result.negated) {1000			if (ctx->retry == 1)1001				cifs_dbg(VFS, "conflicting hard vs. soft mount options\n");1002			ctx->retry = 0;1003		} else1004			ctx->retry = 1;1005		break;1006	case Opt_soft:1007		if (result.negated)1008			ctx->retry = 1;1009		else {1010			if (ctx->retry == 1)1011				cifs_dbg(VFS, "conflicting hard vs soft mount options\n");1012			ctx->retry = 0;1013		}1014		break;1015	case Opt_mapposix:1016		if (result.negated)1017			ctx->remap = false;1018		else {1019			ctx->remap = true;1020			ctx->sfu_remap = false; /* disable SFU mapping */1021		}1022		break;1023	case Opt_mapchars:1024		if (result.negated)1025			ctx->sfu_remap = false;1026		else {1027			ctx->sfu_remap = true;1028			ctx->remap = false; /* disable SFM (mapposix) mapping */1029		}1030		break;1031	case Opt_user_xattr:1032		if (result.negated)1033			ctx->no_xattr = 1;1034		else1035			ctx->no_xattr = 0;1036		break;1037	case Opt_forceuid:1038		if (result.negated)1039			ctx->override_uid = 0;1040		else1041			ctx->override_uid = 1;1042		ctx->forceuid_specified = true;1043		break;1044	case Opt_forcegid:1045		if (result.negated)1046			ctx->override_gid = 0;1047		else1048			ctx->override_gid = 1;1049		ctx->forcegid_specified = true;1050		break;1051	case Opt_perm:1052		if (result.negated)1053			ctx->noperm = 1;1054		else1055			ctx->noperm = 0;1056		break;1057	case Opt_dynperm:1058		if (result.negated)1059			ctx->dynperm = 0;1060		else1061			ctx->dynperm = 1;1062		break;1063	case Opt_sfu:1064		if (result.negated)1065			ctx->sfu_emul = 0;1066		else1067			ctx->sfu_emul = 1;1068		break;1069	case Opt_noblocksend:1070		ctx->noblocksnd = 1;1071		break;1072	case Opt_noautotune:1073		ctx->noautotune = 1;1074		break;1075	case Opt_nolease:1076		ctx->no_lease = 1;1077		break;1078	case Opt_nosparse:1079		ctx->no_sparse = 1;1080		break;1081	case Opt_nodelete:1082		ctx->nodelete = 1;1083		break;1084	case Opt_multichannel:1085		if (result.negated) {1086			ctx->multichannel = false;1087			ctx->max_channels = 1;1088		} else {1089			ctx->multichannel = true;1090			/* if number of channels not specified, default to 2 */1091			if (ctx->max_channels < 2)1092				ctx->max_channels = 2;1093		}1094		break;1095	case Opt_uid:1096		ctx->linux_uid = result.uid;1097		ctx->uid_specified = true;1098		break;1099	case Opt_cruid:1100		ctx->cred_uid = result.uid;1101		ctx->cruid_specified = true;1102		break;1103	case Opt_backupuid:1104		ctx->backupuid = result.uid;1105		ctx->backupuid_specified = true;1106		break;1107	case Opt_backupgid:1108		ctx->backupgid = result.gid;1109		ctx->backupgid_specified = true;1110		break;1111	case Opt_gid:1112		ctx->linux_gid = result.gid;1113		ctx->gid_specified = true;1114		break;1115	case Opt_port:1116		ctx->port = result.uint_32;1117		break;1118	case Opt_file_mode:1119		ctx->file_mode = result.uint_32;1120		break;1121	case Opt_dirmode:1122		ctx->dir_mode = result.uint_32;1123		break;1124	case Opt_min_enc_offload:1125		ctx->min_offload = result.uint_32;1126		break;1127	case Opt_retrans:1128		ctx->retrans = result.uint_32;1129		break;1130	case Opt_blocksize:1131		/*1132		 * inode blocksize realistically should never need to be1133		 * less than 16K or greater than 16M and default is 1MB.1134		 * Note that small inode block sizes (e.g. 64K) can lead1135		 * to very poor performance of common tools like cp and scp1136		 */1137		if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||1138		   (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {1139			cifs_errorf(fc, "%s: Invalid blocksize\n",1140				__func__);1141			goto cifs_parse_mount_err;1142		}1143		ctx->bsize = result.uint_32;1144		ctx->got_bsize = true;1145		break;1146	case Opt_rasize:1147		/*1148		 * readahead size realistically should never need to be1149		 * less than 1M (CIFS_DEFAULT_IOSIZE) or greater than 32M1150		 * (perhaps an exception should be considered in the1151		 * for the case of a large number of channels1152		 * when multichannel is negotiated) since that would lead1153		 * to plenty of parallel I/O in flight to the server.1154		 * Note that smaller read ahead sizes would1155		 * hurt performance of common tools like cp and scp1156		 * which often trigger sequential i/o with read ahead1157		 */1158		if ((result.uint_32 > (8 * SMB3_DEFAULT_IOSIZE)) ||1159		    (result.uint_32 < CIFS_DEFAULT_IOSIZE)) {1160			cifs_errorf(fc, "%s: Invalid rasize %d vs. %d\n",1161				__func__, result.uint_32, SMB3_DEFAULT_IOSIZE);1162			goto cifs_parse_mount_err;1163		}1164		ctx->rasize = result.uint_32;1165		break;1166	case Opt_rsize:1167		ctx->rsize = result.uint_32;1168		ctx->got_rsize = true;1169		break;1170	case Opt_wsize:1171		ctx->wsize = result.uint_32;1172		ctx->got_wsize = true;1173		if (ctx->wsize % PAGE_SIZE != 0) {1174			ctx->wsize = round_down(ctx->wsize, PAGE_SIZE);1175			if (ctx->wsize == 0) {1176				ctx->wsize = PAGE_SIZE;1177				cifs_dbg(VFS, "wsize too small, reset to minimum %ld\n", PAGE_SIZE);1178			} else {1179				cifs_dbg(VFS,1180					 "wsize rounded down to %d to multiple of PAGE_SIZE %ld\n",1181					 ctx->wsize, PAGE_SIZE);1182			}1183		}1184		break;1185	case Opt_acregmax:1186		ctx->acregmax = HZ * result.uint_32;1187		if (ctx->acregmax > CIFS_MAX_ACTIMEO) {1188			cifs_errorf(fc, "acregmax too large\n");1189			goto cifs_parse_mount_err;1190		}1191		break;1192	case Opt_acdirmax:1193		ctx->acdirmax = HZ * result.uint_32;1194		if (ctx->acdirmax > CIFS_MAX_ACTIMEO) {1195			cifs_errorf(fc, "acdirmax too large\n");1196			goto cifs_parse_mount_err;1197		}1198		break;1199	case Opt_actimeo:1200		if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) {1201			cifs_errorf(fc, "timeout too large\n");1202			goto cifs_parse_mount_err;1203		}1204		if ((ctx->acdirmax != CIFS_DEF_ACTIMEO) ||1205		    (ctx->acregmax != CIFS_DEF_ACTIMEO)) {1206			cifs_errorf(fc, "actimeo ignored since acregmax or acdirmax specified\n");1207			break;1208		}1209		ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;1210		break;1211	case Opt_closetimeo:1212		ctx->closetimeo = HZ * result.uint_32;1213		if (ctx->closetimeo > SMB3_MAX_DCLOSETIMEO) {1214			cifs_errorf(fc, "closetimeo too large\n");1215			goto cifs_parse_mount_err;1216		}1217		break;1218	case Opt_echo_interval:1219		ctx->echo_interval = result.uint_32;1220		break;1221	case Opt_snapshot:1222		ctx->snapshot_time = result.uint_64;1223		break;1224	case Opt_max_credits:1225		if (result.uint_32 < 20 || result.uint_32 > 60000) {1226			cifs_errorf(fc, "%s: Invalid max_credits value\n",1227				 __func__);1228			goto cifs_parse_mount_err;1229		}1230		ctx->max_credits = result.uint_32;1231		break;1232	case Opt_max_channels:1233		if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {1234			cifs_errorf(fc, "%s: Invalid max_channels value, needs to be 1-%d\n",1235				 __func__, CIFS_MAX_CHANNELS);1236			goto cifs_parse_mount_err;1237		}1238		ctx->max_channels = result.uint_32;1239		/* If more than one channel requested ... they want multichan */1240		if (result.uint_32 > 1)1241			ctx->multichannel = true;1242		break;1243	case Opt_max_cached_dirs:1244		if (result.uint_32 < 1) {1245			cifs_errorf(fc, "%s: Invalid max_cached_dirs, needs to be 1 or more\n",1246				    __func__);1247			goto cifs_parse_mount_err;1248		}1249		ctx->max_cached_dirs = result.uint_32;1250		break;1251	case Opt_handletimeout:1252		ctx->handle_timeout = result.uint_32;1253		if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {1254			cifs_errorf(fc, "Invalid handle cache timeout, longer than 16 minutes\n");1255			goto cifs_parse_mount_err;1256		}1257		break;1258	case Opt_source:1259		kfree(ctx->UNC);1260		ctx->UNC = NULL;1261		switch (smb3_parse_devname(param->string, ctx)) {1262		case 0:1263			break;1264		case -ENOMEM:1265			cifs_errorf(fc, "Unable to allocate memory for devname\n");1266			goto cifs_parse_mount_err;1267		case -EINVAL:1268			cifs_errorf(fc, "Malformed UNC in devname\n");1269			goto cifs_parse_mount_err;1270		default:1271			cifs_errorf(fc, "Unknown error parsing devname\n");1272			goto cifs_parse_mount_err;1273		}1274		ctx->source = smb3_fs_context_fullpath(ctx, '/');1275		if (IS_ERR(ctx->source)) {1276			ctx->source = NULL;1277			cifs_errorf(fc, "OOM when copying UNC string\n");1278			goto cifs_parse_mount_err;1279		}1280		fc->source = kstrdup(ctx->source, GFP_KERNEL);1281		if (fc->source == NULL) {1282			cifs_errorf(fc, "OOM when copying UNC string\n");1283			goto cifs_parse_mount_err;1284		}1285		break;1286	case Opt_user:1287		kfree(ctx->username);1288		ctx->username = NULL;1289		if (ctx->nullauth)1290			break;1291		if (strlen(param->string) == 0) {1292			/* null user, ie. anonymous authentication */1293			ctx->nullauth = 1;1294			break;1295		}1296 1297		if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) >1298		    CIFS_MAX_USERNAME_LEN) {1299			pr_warn("username too long\n");1300			goto cifs_parse_mount_err;1301		}1302		ctx->username = kstrdup(param->string, GFP_KERNEL);1303		if (ctx->username == NULL) {1304			cifs_errorf(fc, "OOM when copying username string\n");1305			goto cifs_parse_mount_err;1306		}1307		break;1308	case Opt_pass:1309		kfree_sensitive(ctx->password);1310		ctx->password = NULL;1311		if (strlen(param->string) == 0)1312			break;1313 1314		ctx->password = kstrdup(param->string, GFP_KERNEL);1315		if (ctx->password == NULL) {1316			cifs_errorf(fc, "OOM when copying password string\n");1317			goto cifs_parse_mount_err;1318		}1319		break;1320	case Opt_pass2:1321		kfree_sensitive(ctx->password2);1322		ctx->password2 = NULL;1323		if (strlen(param->string) == 0)1324			break;1325 1326		ctx->password2 = kstrdup(param->string, GFP_KERNEL);1327		if (ctx->password2 == NULL) {1328			cifs_errorf(fc, "OOM when copying password2 string\n");1329			goto cifs_parse_mount_err;1330		}1331		break;1332	case Opt_ip:1333		if (strlen(param->string) == 0) {1334			ctx->got_ip = false;1335			break;1336		}1337		if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,1338					  param->string,1339					  strlen(param->string))) {1340			pr_err("bad ip= option (%s)\n", param->string);1341			goto cifs_parse_mount_err;1342		}1343		ctx->got_ip = true;1344		break;1345	case Opt_domain:1346		if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN)1347				== CIFS_MAX_DOMAINNAME_LEN) {1348			pr_warn("domain name too long\n");1349			goto cifs_parse_mount_err;1350		}1351 1352		kfree(ctx->domainname);1353		ctx->domainname = kstrdup(param->string, GFP_KERNEL);1354		if (ctx->domainname == NULL) {1355			cifs_errorf(fc, "OOM when copying domainname string\n");1356			goto cifs_parse_mount_err;1357		}1358		cifs_dbg(FYI, "Domain name set\n");1359		break;1360	case Opt_srcaddr:1361		if (!cifs_convert_address(1362				(struct sockaddr *)&ctx->srcaddr,1363				param->string, strlen(param->string))) {1364			pr_warn("Could not parse srcaddr: %s\n",1365				param->string);1366			goto cifs_parse_mount_err;1367		}1368		break;1369	case Opt_iocharset:1370		if (strnlen(param->string, 1024) >= 65) {1371			pr_warn("iocharset name too long\n");1372			goto cifs_parse_mount_err;1373		}1374 1375		if (strncasecmp(param->string, "default", 7) != 0) {1376			kfree(ctx->iocharset);1377			ctx->iocharset = kstrdup(param->string, GFP_KERNEL);1378			if (ctx->iocharset == NULL) {1379				cifs_errorf(fc, "OOM when copying iocharset string\n");1380				goto cifs_parse_mount_err;1381			}1382		}1383		/* if iocharset not set then load_nls_default1384		 * is used by caller1385		 */1386		cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);1387		break;1388	case Opt_netbiosname:1389		memset(ctx->source_rfc1001_name, 0x20,1390			RFC1001_NAME_LEN);1391		/*1392		 * FIXME: are there cases in which a comma can1393		 * be valid in workstation netbios name (and1394		 * need special handling)?1395		 */1396		for (i = 0; i < RFC1001_NAME_LEN; i++) {1397			/* don't ucase netbiosname for user */1398			if (param->string[i] == 0)1399				break;1400			ctx->source_rfc1001_name[i] = param->string[i];1401		}1402		/* The string has 16th byte zero still from1403		 * set at top of the function1404		 */1405		if (i == RFC1001_NAME_LEN && param->string[i] != 0)1406			pr_warn("netbiosname longer than 15 truncated\n");1407		break;1408	case Opt_servern:1409		/* last byte, type, is 0x20 for servr type */1410		memset(ctx->target_rfc1001_name, 0x20,1411			RFC1001_NAME_LEN_WITH_NULL);1412		/*1413		 * BB are there cases in which a comma can be valid in this1414		 * workstation netbios name (and need special handling)?1415		 */1416 1417		/* user or mount helper must uppercase the netbios name */1418		for (i = 0; i < 15; i++) {1419			if (param->string[i] == 0)1420				break;1421			ctx->target_rfc1001_name[i] = param->string[i];1422		}1423 1424		/* The string has 16th byte zero still from set at top of function */1425		if (i == RFC1001_NAME_LEN && param->string[i] != 0)1426			pr_warn("server netbiosname longer than 15 truncated\n");1427		break;1428	case Opt_ver:1429		/* version of mount userspace tools, not dialect */1430		/* If interface changes in mount.cifs bump to new ver */1431		if (strncasecmp(param->string, "1", 1) == 0) {1432			if (strlen(param->string) > 1) {1433				pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",1434					param->string);1435				goto cifs_parse_mount_err;1436			}1437			/* This is the default */1438			break;1439		}1440		/* For all other value, error */1441		pr_warn("Invalid mount helper version specified\n");1442		goto cifs_parse_mount_err;1443	case Opt_vers:1444		/* protocol version (dialect) */1445		if (cifs_parse_smb_version(fc, param->string, ctx, is_smb3) != 0)1446			goto cifs_parse_mount_err;1447		ctx->got_version = true;1448		break;1449	case Opt_sec:1450		if (cifs_parse_security_flavors(fc, param->string, ctx) != 0)1451			goto cifs_parse_mount_err;1452		break;1453	case Opt_cache:1454		if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0)1455			goto cifs_parse_mount_err;1456		break;1457	case Opt_witness:1458#ifndef CONFIG_CIFS_SWN_UPCALL1459		cifs_errorf(fc, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");1460			goto cifs_parse_mount_err;1461#endif1462		ctx->witness = true;1463		pr_warn_once("Witness protocol support is experimental\n");1464		break;1465	case Opt_rootfs:1466#ifndef CONFIG_CIFS_ROOT1467		cifs_dbg(VFS, "rootfs support requires CONFIG_CIFS_ROOT config option\n");1468		goto cifs_parse_mount_err;1469#endif1470		ctx->rootfs = true;1471		break;1472	case Opt_posixpaths:1473		if (result.negated)1474			ctx->posix_paths = 0;1475		else1476			ctx->posix_paths = 1;1477		break;1478	case Opt_unix:1479		if (result.negated) {1480			if (ctx->linux_ext == 1)1481				pr_warn_once("conflicting posix mount options specified\n");1482			ctx->linux_ext = 0;1483			ctx->no_linux_ext = 1;1484		} else {1485			if (ctx->no_linux_ext == 1)1486				pr_warn_once("conflicting posix mount options specified\n");1487			ctx->linux_ext = 1;1488			ctx->no_linux_ext = 0;1489		}1490		break;1491	case Opt_nocase:1492		ctx->nocase = 1;1493		break;1494	case Opt_brl:1495		if (result.negated) {1496			/*1497			 * turn off mandatory locking in mode1498			 * if remote locking is turned off since the1499			 * local vfs will do advisory1500			 */1501			if (ctx->file_mode ==1502				(S_IALLUGO & ~(S_ISUID | S_IXGRP)))1503				ctx->file_mode = S_IALLUGO;1504			ctx->nobrl =  1;1505		} else1506			ctx->nobrl =  0;1507		break;1508	case Opt_handlecache:1509		if (result.negated)1510			ctx->nohandlecache = 1;1511		else1512			ctx->nohandlecache = 0;1513		break;1514	case Opt_forcemandatorylock:1515		ctx->mand_lock = 1;1516		break;1517	case Opt_setuids:1518		ctx->setuids = result.negated;1519		break;1520	case Opt_intr:1521		ctx->intr = !result.negated;1522		break;1523	case Opt_setuidfromacl:1524		ctx->setuidfromacl = 1;1525		break;1526	case Opt_strictsync:1527		ctx->nostrictsync = result.negated;1528		break;1529	case Opt_serverino:1530		ctx->server_ino = !result.negated;1531		break;1532	case Opt_rwpidforward:1533		ctx->rwpidforward = 1;1534		break;1535	case Opt_modesid:1536		ctx->mode_ace = 1;1537		break;1538	case Opt_cifsacl:1539		ctx->cifs_acl = !result.negated;1540		break;1541	case Opt_acl:1542		ctx->no_psx_acl = result.negated;1543		break;1544	case Opt_locallease:1545		ctx->local_lease = 1;1546		break;1547	case Opt_sign:1548		ctx->sign = true;1549		break;1550	case Opt_ignore_signature:1551		ctx->sign = true;1552		ctx->ignore_signature = true;1553		break;1554	case Opt_seal:1555		/* we do not do the following in secFlags because seal1556		 * is a per tree connection (mount) not a per socket1557		 * or per-smb connection option in the protocol1558		 * vol->secFlg |= CIFSSEC_MUST_SEAL;1559		 */1560		ctx->seal = 1;1561		break;1562	case Opt_noac:1563		pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");1564		break;1565	case Opt_fsc:1566#ifndef CONFIG_CIFS_FSCACHE1567		cifs_errorf(fc, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");1568		goto cifs_parse_mount_err;1569#endif1570		ctx->fsc = true;1571		break;1572	case Opt_mfsymlinks:1573		ctx->mfsymlinks = true;1574		break;1575	case Opt_multiuser:1576		ctx->multiuser = true;1577		break;1578	case Opt_sloppy:1579		ctx->sloppy = true;1580		break;1581	case Opt_nosharesock:1582		ctx->nosharesock = true;1583		break;1584	case Opt_persistent:1585		if (result.negated) {1586			ctx->nopersistent = true;1587			if (ctx->persistent) {1588				cifs_errorf(fc, "persistenthandles mount options conflict\n");1589				goto cifs_parse_mount_err;1590			}1591		} else {1592			ctx->persistent = true;1593			if ((ctx->nopersistent) || (ctx->resilient)) {1594				cifs_errorf(fc, "persistenthandles mount options conflict\n");1595				goto cifs_parse_mount_err;1596			}1597		}1598		break;1599	case Opt_resilient:1600		if (result.negated) {1601			ctx->resilient = false; /* already the default */1602		} else {1603			ctx->resilient = true;1604			if (ctx->persistent) {1605				cifs_errorf(fc, "persistenthandles mount options conflict\n");1606				goto cifs_parse_mount_err;1607			}1608		}1609		break;1610	case Opt_tcp_nodelay:1611		/* tcp nodelay should not usually be needed since we CORK/UNCORK the socket */1612		if (result.negated)1613			ctx->sockopt_tcp_nodelay = false;1614		else1615			ctx->sockopt_tcp_nodelay = true;1616		break;1617	case Opt_domainauto:1618		ctx->domainauto = true;1619		break;1620	case Opt_rdma:1621		ctx->rdma = true;1622		break;1623	case Opt_reparse:1624		if (parse_reparse_flavor(fc, param->string, ctx))1625			goto cifs_parse_mount_err;1626		break;1627	}1628	/* case Opt_ignore: - is ignored as expected ... */1629 1630	return 0;1631 1632 cifs_parse_mount_err:1633	kfree_sensitive(ctx->password);1634	ctx->password = NULL;1635	kfree_sensitive(ctx->password2);1636	ctx->password2 = NULL;1637	return -EINVAL;1638}1639 1640int smb3_init_fs_context(struct fs_context *fc)1641{1642	struct smb3_fs_context *ctx;1643	char *nodename = utsname()->nodename;1644	int i;1645 1646	ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);1647	if (unlikely(!ctx))1648		return -ENOMEM;1649 1650	strscpy(ctx->workstation_name, nodename, sizeof(ctx->workstation_name));1651 1652	/*1653	 * does not have to be perfect mapping since field is1654	 * informational, only used for servers that do not support1655	 * port 445 and it can be overridden at mount time1656	 */1657	memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);1658	for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)1659		ctx->source_rfc1001_name[i] = toupper(nodename[i]);1660 1661	ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;1662	/*1663	 * null target name indicates to use *SMBSERVR default called name1664	 *  if we end up sending RFC1001 session initialize1665	 */1666	ctx->target_rfc1001_name[0] = 0;1667	ctx->cred_uid = current_uid();1668	ctx->linux_uid = current_uid();1669	ctx->linux_gid = current_gid();1670	/* By default 4MB read ahead size, 1MB block size */1671	ctx->bsize = CIFS_DEFAULT_IOSIZE; /* can improve cp performance significantly */1672	ctx->rasize = 0; /* 0 = use default (ie negotiated rsize) for read ahead pages */1673 1674	/*1675	 * default to SFM style remapping of seven reserved characters1676	 * unless user overrides it or we negotiate CIFS POSIX where1677	 * it is unnecessary.  Can not simultaneously use more than one mapping1678	 * since then readdir could list files that open could not open1679	 */1680	ctx->remap = true;1681 1682	/* default to only allowing write access to owner of the mount */1683	ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;1684 1685	/* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */1686	/* default is always to request posix paths. */1687	ctx->posix_paths = 1;1688	/* default to using server inode numbers where available */1689	ctx->server_ino = 1;1690 1691	/* default is to use strict cifs caching semantics */1692	ctx->strict_io = true;1693 1694	ctx->acregmax = CIFS_DEF_ACTIMEO;1695	ctx->acdirmax = CIFS_DEF_ACTIMEO;1696	ctx->closetimeo = SMB3_DEF_DCLOSETIMEO;1697	ctx->max_cached_dirs = MAX_CACHED_FIDS;1698	/* Most clients set timeout to 0, allows server to use its default */1699	ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */1700 1701	/* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */1702	ctx->ops = &smb30_operations;1703	ctx->vals = &smbdefault_values;1704 1705	ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;1706 1707	/* default to no multichannel (single server connection) */1708	ctx->multichannel = false;1709	ctx->max_channels = 1;1710 1711	ctx->backupuid_specified = false; /* no backup intent for a user */1712	ctx->backupgid_specified = false; /* no backup intent for a group */1713 1714	ctx->retrans = 1;1715	ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;1716 1717/*1718 *	short int override_uid = -1;1719 *	short int override_gid = -1;1720 *	char *nodename = strdup(utsname()->nodename);1721 *	struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;1722 */1723 1724	fc->fs_private = ctx;1725	fc->ops = &smb3_fs_context_ops;1726	return 0;1727}1728 1729void1730smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)1731{1732	if (ctx == NULL)1733		return;1734 1735	/*1736	 * Make sure this stays in sync with smb3_fs_context_dup()1737	 */1738	kfree(ctx->username);1739	ctx->username = NULL;1740	kfree_sensitive(ctx->password);1741	ctx->password = NULL;1742	kfree_sensitive(ctx->password2);1743	ctx->password2 = NULL;1744	kfree(ctx->server_hostname);1745	ctx->server_hostname = NULL;1746	kfree(ctx->UNC);1747	ctx->UNC = NULL;1748	kfree(ctx->source);1749	ctx->source = NULL;1750	kfree(ctx->domainname);1751	ctx->domainname = NULL;1752	kfree(ctx->nodename);1753	ctx->nodename = NULL;1754	kfree(ctx->iocharset);1755	ctx->iocharset = NULL;1756	kfree(ctx->prepath);1757	ctx->prepath = NULL;1758	kfree(ctx->leaf_fullpath);1759	ctx->leaf_fullpath = NULL;1760}1761 1762void1763smb3_cleanup_fs_context(struct smb3_fs_context *ctx)1764{1765	if (!ctx)1766		return;1767	smb3_cleanup_fs_context_contents(ctx);1768	kfree(ctx);1769}1770 1771void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)1772{1773	struct smb3_fs_context *ctx = cifs_sb->ctx;1774 1775	if (ctx->nodfs)1776		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;1777	else1778		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS;1779 1780	if (ctx->noperm)1781		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;1782	else1783		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM;1784 1785	if (ctx->setuids)1786		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;1787	else1788		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID;1789 1790	if (ctx->setuidfromacl)1791		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;1792	else1793		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL;1794 1795	if (ctx->server_ino)1796		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;1797	else1798		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;1799 1800	if (ctx->remap)1801		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;1802	else1803		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR;1804 1805	if (ctx->sfu_remap)1806		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;1807	else1808		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;1809 1810	if (ctx->no_xattr)1811		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;1812	else1813		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR;1814 1815	if (ctx->sfu_emul)1816		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;1817	else1818		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL;1819 1820	if (ctx->nobrl)1821		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;1822	else1823		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL;1824 1825	if (ctx->nohandlecache)1826		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;1827	else1828		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;1829 1830	if (ctx->nostrictsync)1831		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;1832	else1833		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC;1834 1835	if (ctx->mand_lock)1836		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;1837	else1838		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL;1839 1840	if (ctx->rwpidforward)1841		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;1842	else1843		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD;1844 1845	if (ctx->mode_ace)1846		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;1847	else1848		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID;1849 1850	if (ctx->cifs_acl)1851		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;1852	else1853		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL;1854 1855	if (ctx->backupuid_specified)1856		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;1857	else1858		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID;1859 1860	if (ctx->backupgid_specified)1861		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;1862	else1863		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID;1864 1865	if (ctx->override_uid)1866		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;1867	else1868		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID;1869 1870	if (ctx->override_gid)1871		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;1872	else1873		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID;1874 1875	if (ctx->dynperm)1876		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;1877	else1878		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM;1879 1880	if (ctx->fsc)1881		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;1882	else1883		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE;1884 1885	if (ctx->multiuser)1886		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |1887					    CIFS_MOUNT_NO_PERM);1888	else1889		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MULTIUSER;1890 1891 1892	if (ctx->strict_io)1893		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;1894	else1895		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO;1896 1897	if (ctx->direct_io)1898		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;1899	else1900		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO;1901 1902	if (ctx->mfsymlinks)1903		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;1904	else1905		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS;1906	if (ctx->mfsymlinks) {1907		if (ctx->sfu_emul) {1908			/*1909			 * Our SFU ("Services for Unix") emulation allows now1910			 * creating new and reading existing SFU symlinks.1911			 * Older Linux kernel versions were not able to neither1912			 * read existing nor create new SFU symlinks. But1913			 * creating and reading SFU style mknod and FIFOs was1914			 * supported for long time. When "mfsymlinks" and1915			 * "sfu" are both enabled at the same time, it allows1916			 * reading both types of symlinks, but will only create1917			 * them with mfsymlinks format. This allows better1918			 * Apple compatibility, compatibility with older Linux1919			 * kernel clients (probably better for Samba too)1920			 * while still recognizing old Windows style symlinks.1921			 */1922			cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");1923		}1924	}1925	cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SHUTDOWN;1926 1927	return;1928}1929