162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2020, Microsoft Corporation. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Author(s): Steve French <stfrench@microsoft.com> 662306a36Sopenharmony_ci * David Howells <dhowells@redhat.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/* 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/nsproxy.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci#include <linux/magic.h> 1462306a36Sopenharmony_ci#include <linux/security.h> 1562306a36Sopenharmony_ci#include <net/net_namespace.h> 1662306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL 1762306a36Sopenharmony_ci#include "dfs_cache.h" 1862306a36Sopenharmony_ci#endif 1962306a36Sopenharmony_ci*/ 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <linux/ctype.h> 2262306a36Sopenharmony_ci#include <linux/fs_context.h> 2362306a36Sopenharmony_ci#include <linux/fs_parser.h> 2462306a36Sopenharmony_ci#include <linux/fs.h> 2562306a36Sopenharmony_ci#include <linux/mount.h> 2662306a36Sopenharmony_ci#include <linux/parser.h> 2762306a36Sopenharmony_ci#include <linux/utsname.h> 2862306a36Sopenharmony_ci#include "cifsfs.h" 2962306a36Sopenharmony_ci#include "cifspdu.h" 3062306a36Sopenharmony_ci#include "cifsglob.h" 3162306a36Sopenharmony_ci#include "cifsproto.h" 3262306a36Sopenharmony_ci#include "cifs_unicode.h" 3362306a36Sopenharmony_ci#include "cifs_debug.h" 3462306a36Sopenharmony_ci#include "cifs_fs_sb.h" 3562306a36Sopenharmony_ci#include "ntlmssp.h" 3662306a36Sopenharmony_ci#include "nterr.h" 3762306a36Sopenharmony_ci#include "rfc1002pdu.h" 3862306a36Sopenharmony_ci#include "fs_context.h" 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic DEFINE_MUTEX(cifs_mount_mutex); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic const match_table_t cifs_smb_version_tokens = { 4362306a36Sopenharmony_ci { Smb_1, SMB1_VERSION_STRING }, 4462306a36Sopenharmony_ci { Smb_20, SMB20_VERSION_STRING}, 4562306a36Sopenharmony_ci { Smb_21, SMB21_VERSION_STRING }, 4662306a36Sopenharmony_ci { Smb_30, SMB30_VERSION_STRING }, 4762306a36Sopenharmony_ci { Smb_302, SMB302_VERSION_STRING }, 4862306a36Sopenharmony_ci { Smb_302, ALT_SMB302_VERSION_STRING }, 4962306a36Sopenharmony_ci { Smb_311, SMB311_VERSION_STRING }, 5062306a36Sopenharmony_ci { Smb_311, ALT_SMB311_VERSION_STRING }, 5162306a36Sopenharmony_ci { Smb_3any, SMB3ANY_VERSION_STRING }, 5262306a36Sopenharmony_ci { Smb_default, SMBDEFAULT_VERSION_STRING }, 5362306a36Sopenharmony_ci { Smb_version_err, NULL } 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic const match_table_t cifs_secflavor_tokens = { 5762306a36Sopenharmony_ci { Opt_sec_krb5, "krb5" }, 5862306a36Sopenharmony_ci { Opt_sec_krb5i, "krb5i" }, 5962306a36Sopenharmony_ci { Opt_sec_krb5p, "krb5p" }, 6062306a36Sopenharmony_ci { Opt_sec_ntlmsspi, "ntlmsspi" }, 6162306a36Sopenharmony_ci { Opt_sec_ntlmssp, "ntlmssp" }, 6262306a36Sopenharmony_ci { Opt_sec_ntlmv2, "nontlm" }, 6362306a36Sopenharmony_ci { Opt_sec_ntlmv2, "ntlmv2" }, 6462306a36Sopenharmony_ci { Opt_sec_ntlmv2i, "ntlmv2i" }, 6562306a36Sopenharmony_ci { Opt_sec_none, "none" }, 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci { Opt_sec_err, NULL } 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ciconst struct fs_parameter_spec smb3_fs_parameters[] = { 7162306a36Sopenharmony_ci /* Mount options that take no arguments */ 7262306a36Sopenharmony_ci fsparam_flag_no("user_xattr", Opt_user_xattr), 7362306a36Sopenharmony_ci fsparam_flag_no("forceuid", Opt_forceuid), 7462306a36Sopenharmony_ci fsparam_flag_no("multichannel", Opt_multichannel), 7562306a36Sopenharmony_ci fsparam_flag_no("forcegid", Opt_forcegid), 7662306a36Sopenharmony_ci fsparam_flag("noblocksend", Opt_noblocksend), 7762306a36Sopenharmony_ci fsparam_flag("noautotune", Opt_noautotune), 7862306a36Sopenharmony_ci fsparam_flag("nolease", Opt_nolease), 7962306a36Sopenharmony_ci fsparam_flag_no("hard", Opt_hard), 8062306a36Sopenharmony_ci fsparam_flag_no("soft", Opt_soft), 8162306a36Sopenharmony_ci fsparam_flag_no("perm", Opt_perm), 8262306a36Sopenharmony_ci fsparam_flag("nodelete", Opt_nodelete), 8362306a36Sopenharmony_ci fsparam_flag_no("mapposix", Opt_mapposix), 8462306a36Sopenharmony_ci fsparam_flag("mapchars", Opt_mapchars), 8562306a36Sopenharmony_ci fsparam_flag("nomapchars", Opt_nomapchars), 8662306a36Sopenharmony_ci fsparam_flag_no("sfu", Opt_sfu), 8762306a36Sopenharmony_ci fsparam_flag("nodfs", Opt_nodfs), 8862306a36Sopenharmony_ci fsparam_flag_no("posixpaths", Opt_posixpaths), 8962306a36Sopenharmony_ci fsparam_flag_no("unix", Opt_unix), 9062306a36Sopenharmony_ci fsparam_flag_no("linux", Opt_unix), 9162306a36Sopenharmony_ci fsparam_flag_no("posix", Opt_unix), 9262306a36Sopenharmony_ci fsparam_flag("nocase", Opt_nocase), 9362306a36Sopenharmony_ci fsparam_flag("ignorecase", Opt_nocase), 9462306a36Sopenharmony_ci fsparam_flag_no("brl", Opt_brl), 9562306a36Sopenharmony_ci fsparam_flag_no("handlecache", Opt_handlecache), 9662306a36Sopenharmony_ci fsparam_flag("forcemandatorylock", Opt_forcemandatorylock), 9762306a36Sopenharmony_ci fsparam_flag("forcemand", Opt_forcemandatorylock), 9862306a36Sopenharmony_ci fsparam_flag("setuidfromacl", Opt_setuidfromacl), 9962306a36Sopenharmony_ci fsparam_flag("idsfromsid", Opt_setuidfromacl), 10062306a36Sopenharmony_ci fsparam_flag_no("setuids", Opt_setuids), 10162306a36Sopenharmony_ci fsparam_flag_no("dynperm", Opt_dynperm), 10262306a36Sopenharmony_ci fsparam_flag_no("intr", Opt_intr), 10362306a36Sopenharmony_ci fsparam_flag_no("strictsync", Opt_strictsync), 10462306a36Sopenharmony_ci fsparam_flag_no("serverino", Opt_serverino), 10562306a36Sopenharmony_ci fsparam_flag("rwpidforward", Opt_rwpidforward), 10662306a36Sopenharmony_ci fsparam_flag("cifsacl", Opt_cifsacl), 10762306a36Sopenharmony_ci fsparam_flag_no("acl", Opt_acl), 10862306a36Sopenharmony_ci fsparam_flag("locallease", Opt_locallease), 10962306a36Sopenharmony_ci fsparam_flag("sign", Opt_sign), 11062306a36Sopenharmony_ci fsparam_flag("ignore_signature", Opt_ignore_signature), 11162306a36Sopenharmony_ci fsparam_flag("signloosely", Opt_ignore_signature), 11262306a36Sopenharmony_ci fsparam_flag("seal", Opt_seal), 11362306a36Sopenharmony_ci fsparam_flag("noac", Opt_noac), 11462306a36Sopenharmony_ci fsparam_flag("fsc", Opt_fsc), 11562306a36Sopenharmony_ci fsparam_flag("mfsymlinks", Opt_mfsymlinks), 11662306a36Sopenharmony_ci fsparam_flag("multiuser", Opt_multiuser), 11762306a36Sopenharmony_ci fsparam_flag("sloppy", Opt_sloppy), 11862306a36Sopenharmony_ci fsparam_flag("nosharesock", Opt_nosharesock), 11962306a36Sopenharmony_ci fsparam_flag_no("persistenthandles", Opt_persistent), 12062306a36Sopenharmony_ci fsparam_flag_no("resilienthandles", Opt_resilient), 12162306a36Sopenharmony_ci fsparam_flag_no("tcpnodelay", Opt_tcp_nodelay), 12262306a36Sopenharmony_ci fsparam_flag("nosparse", Opt_nosparse), 12362306a36Sopenharmony_ci fsparam_flag("domainauto", Opt_domainauto), 12462306a36Sopenharmony_ci fsparam_flag("rdma", Opt_rdma), 12562306a36Sopenharmony_ci fsparam_flag("modesid", Opt_modesid), 12662306a36Sopenharmony_ci fsparam_flag("modefromsid", Opt_modesid), 12762306a36Sopenharmony_ci fsparam_flag("rootfs", Opt_rootfs), 12862306a36Sopenharmony_ci fsparam_flag("compress", Opt_compress), 12962306a36Sopenharmony_ci fsparam_flag("witness", Opt_witness), 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* Mount options which take numeric value */ 13262306a36Sopenharmony_ci fsparam_u32("backupuid", Opt_backupuid), 13362306a36Sopenharmony_ci fsparam_u32("backupgid", Opt_backupgid), 13462306a36Sopenharmony_ci fsparam_u32("uid", Opt_uid), 13562306a36Sopenharmony_ci fsparam_u32("cruid", Opt_cruid), 13662306a36Sopenharmony_ci fsparam_u32("gid", Opt_gid), 13762306a36Sopenharmony_ci fsparam_u32("file_mode", Opt_file_mode), 13862306a36Sopenharmony_ci fsparam_u32("dirmode", Opt_dirmode), 13962306a36Sopenharmony_ci fsparam_u32("dir_mode", Opt_dirmode), 14062306a36Sopenharmony_ci fsparam_u32("port", Opt_port), 14162306a36Sopenharmony_ci fsparam_u32("min_enc_offload", Opt_min_enc_offload), 14262306a36Sopenharmony_ci fsparam_u32("esize", Opt_min_enc_offload), 14362306a36Sopenharmony_ci fsparam_u32("bsize", Opt_blocksize), 14462306a36Sopenharmony_ci fsparam_u32("rasize", Opt_rasize), 14562306a36Sopenharmony_ci fsparam_u32("rsize", Opt_rsize), 14662306a36Sopenharmony_ci fsparam_u32("wsize", Opt_wsize), 14762306a36Sopenharmony_ci fsparam_u32("actimeo", Opt_actimeo), 14862306a36Sopenharmony_ci fsparam_u32("acdirmax", Opt_acdirmax), 14962306a36Sopenharmony_ci fsparam_u32("acregmax", Opt_acregmax), 15062306a36Sopenharmony_ci fsparam_u32("closetimeo", Opt_closetimeo), 15162306a36Sopenharmony_ci fsparam_u32("echo_interval", Opt_echo_interval), 15262306a36Sopenharmony_ci fsparam_u32("max_credits", Opt_max_credits), 15362306a36Sopenharmony_ci fsparam_u32("max_cached_dirs", Opt_max_cached_dirs), 15462306a36Sopenharmony_ci fsparam_u32("handletimeout", Opt_handletimeout), 15562306a36Sopenharmony_ci fsparam_u64("snapshot", Opt_snapshot), 15662306a36Sopenharmony_ci fsparam_u32("max_channels", Opt_max_channels), 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* Mount options which take string value */ 15962306a36Sopenharmony_ci fsparam_string("source", Opt_source), 16062306a36Sopenharmony_ci fsparam_string("user", Opt_user), 16162306a36Sopenharmony_ci fsparam_string("username", Opt_user), 16262306a36Sopenharmony_ci fsparam_string("pass", Opt_pass), 16362306a36Sopenharmony_ci fsparam_string("password", Opt_pass), 16462306a36Sopenharmony_ci fsparam_string("ip", Opt_ip), 16562306a36Sopenharmony_ci fsparam_string("addr", Opt_ip), 16662306a36Sopenharmony_ci fsparam_string("domain", Opt_domain), 16762306a36Sopenharmony_ci fsparam_string("dom", Opt_domain), 16862306a36Sopenharmony_ci fsparam_string("srcaddr", Opt_srcaddr), 16962306a36Sopenharmony_ci fsparam_string("iocharset", Opt_iocharset), 17062306a36Sopenharmony_ci fsparam_string("netbiosname", Opt_netbiosname), 17162306a36Sopenharmony_ci fsparam_string("servern", Opt_servern), 17262306a36Sopenharmony_ci fsparam_string("ver", Opt_ver), 17362306a36Sopenharmony_ci fsparam_string("vers", Opt_vers), 17462306a36Sopenharmony_ci fsparam_string("sec", Opt_sec), 17562306a36Sopenharmony_ci fsparam_string("cache", Opt_cache), 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* Arguments that should be ignored */ 17862306a36Sopenharmony_ci fsparam_flag("guest", Opt_ignore), 17962306a36Sopenharmony_ci fsparam_flag("noatime", Opt_ignore), 18062306a36Sopenharmony_ci fsparam_flag("relatime", Opt_ignore), 18162306a36Sopenharmony_ci fsparam_flag("_netdev", Opt_ignore), 18262306a36Sopenharmony_ci fsparam_flag_no("suid", Opt_ignore), 18362306a36Sopenharmony_ci fsparam_flag_no("exec", Opt_ignore), 18462306a36Sopenharmony_ci fsparam_flag_no("dev", Opt_ignore), 18562306a36Sopenharmony_ci fsparam_flag_no("mand", Opt_ignore), 18662306a36Sopenharmony_ci fsparam_flag_no("auto", Opt_ignore), 18762306a36Sopenharmony_ci fsparam_string("cred", Opt_ignore), 18862306a36Sopenharmony_ci fsparam_string("credentials", Opt_ignore), 18962306a36Sopenharmony_ci /* 19062306a36Sopenharmony_ci * UNC and prefixpath is now extracted from Opt_source 19162306a36Sopenharmony_ci * in the new mount API so we can just ignore them going forward. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ci fsparam_string("unc", Opt_ignore), 19462306a36Sopenharmony_ci fsparam_string("prefixpath", Opt_ignore), 19562306a36Sopenharmony_ci {} 19662306a36Sopenharmony_ci}; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic int 19962306a36Sopenharmony_cicifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_context *ctx) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci substring_t args[MAX_OPT_ARGS]; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* 20562306a36Sopenharmony_ci * With mount options, the last one should win. Reset any existing 20662306a36Sopenharmony_ci * settings back to default. 20762306a36Sopenharmony_ci */ 20862306a36Sopenharmony_ci ctx->sectype = Unspecified; 20962306a36Sopenharmony_ci ctx->sign = false; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci switch (match_token(value, cifs_secflavor_tokens, args)) { 21262306a36Sopenharmony_ci case Opt_sec_krb5p: 21362306a36Sopenharmony_ci cifs_errorf(fc, "sec=krb5p is not supported. Use sec=krb5,seal instead\n"); 21462306a36Sopenharmony_ci return 1; 21562306a36Sopenharmony_ci case Opt_sec_krb5i: 21662306a36Sopenharmony_ci ctx->sign = true; 21762306a36Sopenharmony_ci fallthrough; 21862306a36Sopenharmony_ci case Opt_sec_krb5: 21962306a36Sopenharmony_ci ctx->sectype = Kerberos; 22062306a36Sopenharmony_ci break; 22162306a36Sopenharmony_ci case Opt_sec_ntlmsspi: 22262306a36Sopenharmony_ci ctx->sign = true; 22362306a36Sopenharmony_ci fallthrough; 22462306a36Sopenharmony_ci case Opt_sec_ntlmssp: 22562306a36Sopenharmony_ci ctx->sectype = RawNTLMSSP; 22662306a36Sopenharmony_ci break; 22762306a36Sopenharmony_ci case Opt_sec_ntlmv2i: 22862306a36Sopenharmony_ci ctx->sign = true; 22962306a36Sopenharmony_ci fallthrough; 23062306a36Sopenharmony_ci case Opt_sec_ntlmv2: 23162306a36Sopenharmony_ci ctx->sectype = NTLMv2; 23262306a36Sopenharmony_ci break; 23362306a36Sopenharmony_ci case Opt_sec_none: 23462306a36Sopenharmony_ci ctx->nullauth = 1; 23562306a36Sopenharmony_ci kfree(ctx->username); 23662306a36Sopenharmony_ci ctx->username = NULL; 23762306a36Sopenharmony_ci break; 23862306a36Sopenharmony_ci default: 23962306a36Sopenharmony_ci cifs_errorf(fc, "bad security option: %s\n", value); 24062306a36Sopenharmony_ci return 1; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci return 0; 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic const match_table_t cifs_cacheflavor_tokens = { 24762306a36Sopenharmony_ci { Opt_cache_loose, "loose" }, 24862306a36Sopenharmony_ci { Opt_cache_strict, "strict" }, 24962306a36Sopenharmony_ci { Opt_cache_none, "none" }, 25062306a36Sopenharmony_ci { Opt_cache_ro, "ro" }, 25162306a36Sopenharmony_ci { Opt_cache_rw, "singleclient" }, 25262306a36Sopenharmony_ci { Opt_cache_err, NULL } 25362306a36Sopenharmony_ci}; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic int 25662306a36Sopenharmony_cicifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_context *ctx) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci substring_t args[MAX_OPT_ARGS]; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci switch (match_token(value, cifs_cacheflavor_tokens, args)) { 26162306a36Sopenharmony_ci case Opt_cache_loose: 26262306a36Sopenharmony_ci ctx->direct_io = false; 26362306a36Sopenharmony_ci ctx->strict_io = false; 26462306a36Sopenharmony_ci ctx->cache_ro = false; 26562306a36Sopenharmony_ci ctx->cache_rw = false; 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci case Opt_cache_strict: 26862306a36Sopenharmony_ci ctx->direct_io = false; 26962306a36Sopenharmony_ci ctx->strict_io = true; 27062306a36Sopenharmony_ci ctx->cache_ro = false; 27162306a36Sopenharmony_ci ctx->cache_rw = false; 27262306a36Sopenharmony_ci break; 27362306a36Sopenharmony_ci case Opt_cache_none: 27462306a36Sopenharmony_ci ctx->direct_io = true; 27562306a36Sopenharmony_ci ctx->strict_io = false; 27662306a36Sopenharmony_ci ctx->cache_ro = false; 27762306a36Sopenharmony_ci ctx->cache_rw = false; 27862306a36Sopenharmony_ci break; 27962306a36Sopenharmony_ci case Opt_cache_ro: 28062306a36Sopenharmony_ci ctx->direct_io = false; 28162306a36Sopenharmony_ci ctx->strict_io = false; 28262306a36Sopenharmony_ci ctx->cache_ro = true; 28362306a36Sopenharmony_ci ctx->cache_rw = false; 28462306a36Sopenharmony_ci break; 28562306a36Sopenharmony_ci case Opt_cache_rw: 28662306a36Sopenharmony_ci ctx->direct_io = false; 28762306a36Sopenharmony_ci ctx->strict_io = false; 28862306a36Sopenharmony_ci ctx->cache_ro = false; 28962306a36Sopenharmony_ci ctx->cache_rw = true; 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci default: 29262306a36Sopenharmony_ci cifs_errorf(fc, "bad cache= option: %s\n", value); 29362306a36Sopenharmony_ci return 1; 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci return 0; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci#define DUP_CTX_STR(field) \ 29962306a36Sopenharmony_cido { \ 30062306a36Sopenharmony_ci if (ctx->field) { \ 30162306a36Sopenharmony_ci new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC); \ 30262306a36Sopenharmony_ci if (new_ctx->field == NULL) { \ 30362306a36Sopenharmony_ci smb3_cleanup_fs_context_contents(new_ctx); \ 30462306a36Sopenharmony_ci return -ENOMEM; \ 30562306a36Sopenharmony_ci } \ 30662306a36Sopenharmony_ci } \ 30762306a36Sopenharmony_ci} while (0) 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ciint 31062306a36Sopenharmony_cismb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci memcpy(new_ctx, ctx, sizeof(*ctx)); 31362306a36Sopenharmony_ci new_ctx->prepath = NULL; 31462306a36Sopenharmony_ci new_ctx->nodename = NULL; 31562306a36Sopenharmony_ci new_ctx->username = NULL; 31662306a36Sopenharmony_ci new_ctx->password = NULL; 31762306a36Sopenharmony_ci new_ctx->server_hostname = NULL; 31862306a36Sopenharmony_ci new_ctx->domainname = NULL; 31962306a36Sopenharmony_ci new_ctx->UNC = NULL; 32062306a36Sopenharmony_ci new_ctx->source = NULL; 32162306a36Sopenharmony_ci new_ctx->iocharset = NULL; 32262306a36Sopenharmony_ci new_ctx->leaf_fullpath = NULL; 32362306a36Sopenharmony_ci /* 32462306a36Sopenharmony_ci * Make sure to stay in sync with smb3_cleanup_fs_context_contents() 32562306a36Sopenharmony_ci */ 32662306a36Sopenharmony_ci DUP_CTX_STR(prepath); 32762306a36Sopenharmony_ci DUP_CTX_STR(username); 32862306a36Sopenharmony_ci DUP_CTX_STR(password); 32962306a36Sopenharmony_ci DUP_CTX_STR(server_hostname); 33062306a36Sopenharmony_ci DUP_CTX_STR(UNC); 33162306a36Sopenharmony_ci DUP_CTX_STR(source); 33262306a36Sopenharmony_ci DUP_CTX_STR(domainname); 33362306a36Sopenharmony_ci DUP_CTX_STR(nodename); 33462306a36Sopenharmony_ci DUP_CTX_STR(iocharset); 33562306a36Sopenharmony_ci DUP_CTX_STR(leaf_fullpath); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci return 0; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic int 34162306a36Sopenharmony_cicifs_parse_smb_version(struct fs_context *fc, char *value, struct smb3_fs_context *ctx, bool is_smb3) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci substring_t args[MAX_OPT_ARGS]; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci switch (match_token(value, cifs_smb_version_tokens, args)) { 34662306a36Sopenharmony_ci#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 34762306a36Sopenharmony_ci case Smb_1: 34862306a36Sopenharmony_ci if (disable_legacy_dialects) { 34962306a36Sopenharmony_ci cifs_errorf(fc, "mount with legacy dialect disabled\n"); 35062306a36Sopenharmony_ci return 1; 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci if (is_smb3) { 35362306a36Sopenharmony_ci cifs_errorf(fc, "vers=1.0 (cifs) not permitted when mounting with smb3\n"); 35462306a36Sopenharmony_ci return 1; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci cifs_errorf(fc, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n"); 35762306a36Sopenharmony_ci ctx->ops = &smb1_operations; 35862306a36Sopenharmony_ci ctx->vals = &smb1_values; 35962306a36Sopenharmony_ci break; 36062306a36Sopenharmony_ci case Smb_20: 36162306a36Sopenharmony_ci if (disable_legacy_dialects) { 36262306a36Sopenharmony_ci cifs_errorf(fc, "mount with legacy dialect disabled\n"); 36362306a36Sopenharmony_ci return 1; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci if (is_smb3) { 36662306a36Sopenharmony_ci cifs_errorf(fc, "vers=2.0 not permitted when mounting with smb3\n"); 36762306a36Sopenharmony_ci return 1; 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci ctx->ops = &smb20_operations; 37062306a36Sopenharmony_ci ctx->vals = &smb20_values; 37162306a36Sopenharmony_ci break; 37262306a36Sopenharmony_ci#else 37362306a36Sopenharmony_ci case Smb_1: 37462306a36Sopenharmony_ci cifs_errorf(fc, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n"); 37562306a36Sopenharmony_ci return 1; 37662306a36Sopenharmony_ci case Smb_20: 37762306a36Sopenharmony_ci cifs_errorf(fc, "vers=2.0 mount not permitted when legacy dialects disabled\n"); 37862306a36Sopenharmony_ci return 1; 37962306a36Sopenharmony_ci#endif /* CIFS_ALLOW_INSECURE_LEGACY */ 38062306a36Sopenharmony_ci case Smb_21: 38162306a36Sopenharmony_ci ctx->ops = &smb21_operations; 38262306a36Sopenharmony_ci ctx->vals = &smb21_values; 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci case Smb_30: 38562306a36Sopenharmony_ci ctx->ops = &smb30_operations; 38662306a36Sopenharmony_ci ctx->vals = &smb30_values; 38762306a36Sopenharmony_ci break; 38862306a36Sopenharmony_ci case Smb_302: 38962306a36Sopenharmony_ci ctx->ops = &smb30_operations; /* currently identical with 3.0 */ 39062306a36Sopenharmony_ci ctx->vals = &smb302_values; 39162306a36Sopenharmony_ci break; 39262306a36Sopenharmony_ci case Smb_311: 39362306a36Sopenharmony_ci ctx->ops = &smb311_operations; 39462306a36Sopenharmony_ci ctx->vals = &smb311_values; 39562306a36Sopenharmony_ci break; 39662306a36Sopenharmony_ci case Smb_3any: 39762306a36Sopenharmony_ci ctx->ops = &smb30_operations; /* currently identical with 3.0 */ 39862306a36Sopenharmony_ci ctx->vals = &smb3any_values; 39962306a36Sopenharmony_ci break; 40062306a36Sopenharmony_ci case Smb_default: 40162306a36Sopenharmony_ci ctx->ops = &smb30_operations; 40262306a36Sopenharmony_ci ctx->vals = &smbdefault_values; 40362306a36Sopenharmony_ci break; 40462306a36Sopenharmony_ci default: 40562306a36Sopenharmony_ci cifs_errorf(fc, "Unknown vers= option specified: %s\n", value); 40662306a36Sopenharmony_ci return 1; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci return 0; 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ciint smb3_parse_opt(const char *options, const char *key, char **val) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci int rc = -ENOENT; 41462306a36Sopenharmony_ci char *opts, *orig, *p; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci orig = opts = kstrdup(options, GFP_KERNEL); 41762306a36Sopenharmony_ci if (!opts) 41862306a36Sopenharmony_ci return -ENOMEM; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci while ((p = strsep(&opts, ","))) { 42162306a36Sopenharmony_ci char *nval; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci if (!*p) 42462306a36Sopenharmony_ci continue; 42562306a36Sopenharmony_ci if (strncasecmp(p, key, strlen(key))) 42662306a36Sopenharmony_ci continue; 42762306a36Sopenharmony_ci nval = strchr(p, '='); 42862306a36Sopenharmony_ci if (nval) { 42962306a36Sopenharmony_ci if (nval == p) 43062306a36Sopenharmony_ci continue; 43162306a36Sopenharmony_ci *nval++ = 0; 43262306a36Sopenharmony_ci *val = kstrdup(nval, GFP_KERNEL); 43362306a36Sopenharmony_ci rc = !*val ? -ENOMEM : 0; 43462306a36Sopenharmony_ci goto out; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ciout: 43862306a36Sopenharmony_ci kfree(orig); 43962306a36Sopenharmony_ci return rc; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci/* 44362306a36Sopenharmony_ci * Remove duplicate path delimiters. Windows is supposed to do that 44462306a36Sopenharmony_ci * but there are some bugs that prevent rename from working if there are 44562306a36Sopenharmony_ci * multiple delimiters. 44662306a36Sopenharmony_ci * 44762306a36Sopenharmony_ci * Return a sanitized duplicate of @path or NULL for empty prefix paths. 44862306a36Sopenharmony_ci * Otherwise, return ERR_PTR. 44962306a36Sopenharmony_ci * 45062306a36Sopenharmony_ci * @gfp indicates the GFP_* flags for kstrdup. 45162306a36Sopenharmony_ci * The caller is responsible for freeing the original. 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_ci#define IS_DELIM(c) ((c) == '/' || (c) == '\\') 45462306a36Sopenharmony_cichar *cifs_sanitize_prepath(char *prepath, gfp_t gfp) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci char *cursor1 = prepath, *cursor2 = prepath; 45762306a36Sopenharmony_ci char *s; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci /* skip all prepended delimiters */ 46062306a36Sopenharmony_ci while (IS_DELIM(*cursor1)) 46162306a36Sopenharmony_ci cursor1++; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* copy the first letter */ 46462306a36Sopenharmony_ci *cursor2 = *cursor1; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci /* copy the remainder... */ 46762306a36Sopenharmony_ci while (*(cursor1++)) { 46862306a36Sopenharmony_ci /* ... skipping all duplicated delimiters */ 46962306a36Sopenharmony_ci if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2)) 47062306a36Sopenharmony_ci continue; 47162306a36Sopenharmony_ci *(++cursor2) = *cursor1; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci /* if the last character is a delimiter, skip it */ 47562306a36Sopenharmony_ci if (IS_DELIM(*(cursor2 - 1))) 47662306a36Sopenharmony_ci cursor2--; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci *cursor2 = '\0'; 47962306a36Sopenharmony_ci if (!*prepath) 48062306a36Sopenharmony_ci return NULL; 48162306a36Sopenharmony_ci s = kstrdup(prepath, gfp); 48262306a36Sopenharmony_ci if (!s) 48362306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 48462306a36Sopenharmony_ci return s; 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci/* 48862306a36Sopenharmony_ci * Return full path based on the values of @ctx->{UNC,prepath}. 48962306a36Sopenharmony_ci * 49062306a36Sopenharmony_ci * It is assumed that both values were already parsed by smb3_parse_devname(). 49162306a36Sopenharmony_ci */ 49262306a36Sopenharmony_cichar *smb3_fs_context_fullpath(const struct smb3_fs_context *ctx, char dirsep) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci size_t ulen, plen; 49562306a36Sopenharmony_ci char *s; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci ulen = strlen(ctx->UNC); 49862306a36Sopenharmony_ci plen = ctx->prepath ? strlen(ctx->prepath) + 1 : 0; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci s = kmalloc(ulen + plen + 1, GFP_KERNEL); 50162306a36Sopenharmony_ci if (!s) 50262306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 50362306a36Sopenharmony_ci memcpy(s, ctx->UNC, ulen); 50462306a36Sopenharmony_ci if (plen) { 50562306a36Sopenharmony_ci s[ulen] = dirsep; 50662306a36Sopenharmony_ci memcpy(s + ulen + 1, ctx->prepath, plen); 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci s[ulen + plen] = '\0'; 50962306a36Sopenharmony_ci convert_delimiter(s, dirsep); 51062306a36Sopenharmony_ci return s; 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci/* 51462306a36Sopenharmony_ci * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath 51562306a36Sopenharmony_ci * fields with the result. Returns 0 on success and an error otherwise 51662306a36Sopenharmony_ci * (e.g. ENOMEM or EINVAL) 51762306a36Sopenharmony_ci */ 51862306a36Sopenharmony_ciint 51962306a36Sopenharmony_cismb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci char *pos; 52262306a36Sopenharmony_ci const char *delims = "/\\"; 52362306a36Sopenharmony_ci size_t len; 52462306a36Sopenharmony_ci int rc; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (unlikely(!devname || !*devname)) { 52762306a36Sopenharmony_ci cifs_dbg(VFS, "Device name not specified\n"); 52862306a36Sopenharmony_ci return -EINVAL; 52962306a36Sopenharmony_ci } 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci /* make sure we have a valid UNC double delimiter prefix */ 53262306a36Sopenharmony_ci len = strspn(devname, delims); 53362306a36Sopenharmony_ci if (len != 2) 53462306a36Sopenharmony_ci return -EINVAL; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci /* find delimiter between host and sharename */ 53762306a36Sopenharmony_ci pos = strpbrk(devname + 2, delims); 53862306a36Sopenharmony_ci if (!pos) 53962306a36Sopenharmony_ci return -EINVAL; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci /* record the server hostname */ 54262306a36Sopenharmony_ci kfree(ctx->server_hostname); 54362306a36Sopenharmony_ci ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL); 54462306a36Sopenharmony_ci if (!ctx->server_hostname) 54562306a36Sopenharmony_ci return -ENOMEM; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci /* skip past delimiter */ 54862306a36Sopenharmony_ci ++pos; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* now go until next delimiter or end of string */ 55162306a36Sopenharmony_ci len = strcspn(pos, delims); 55262306a36Sopenharmony_ci if (!len) 55362306a36Sopenharmony_ci return -EINVAL; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci /* move "pos" up to delimiter or NULL */ 55662306a36Sopenharmony_ci pos += len; 55762306a36Sopenharmony_ci kfree(ctx->UNC); 55862306a36Sopenharmony_ci ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL); 55962306a36Sopenharmony_ci if (!ctx->UNC) 56062306a36Sopenharmony_ci return -ENOMEM; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci convert_delimiter(ctx->UNC, '\\'); 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci /* skip any delimiter */ 56562306a36Sopenharmony_ci if (*pos == '/' || *pos == '\\') 56662306a36Sopenharmony_ci pos++; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci kfree(ctx->prepath); 56962306a36Sopenharmony_ci ctx->prepath = NULL; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci /* If pos is NULL then no prepath */ 57262306a36Sopenharmony_ci if (!*pos) 57362306a36Sopenharmony_ci return 0; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci ctx->prepath = cifs_sanitize_prepath(pos, GFP_KERNEL); 57662306a36Sopenharmony_ci if (IS_ERR(ctx->prepath)) { 57762306a36Sopenharmony_ci rc = PTR_ERR(ctx->prepath); 57862306a36Sopenharmony_ci ctx->prepath = NULL; 57962306a36Sopenharmony_ci return rc; 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci return 0; 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cistatic void smb3_fs_context_free(struct fs_context *fc); 58662306a36Sopenharmony_cistatic int smb3_fs_context_parse_param(struct fs_context *fc, 58762306a36Sopenharmony_ci struct fs_parameter *param); 58862306a36Sopenharmony_cistatic int smb3_fs_context_parse_monolithic(struct fs_context *fc, 58962306a36Sopenharmony_ci void *data); 59062306a36Sopenharmony_cistatic int smb3_get_tree(struct fs_context *fc); 59162306a36Sopenharmony_cistatic int smb3_reconfigure(struct fs_context *fc); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cistatic const struct fs_context_operations smb3_fs_context_ops = { 59462306a36Sopenharmony_ci .free = smb3_fs_context_free, 59562306a36Sopenharmony_ci .parse_param = smb3_fs_context_parse_param, 59662306a36Sopenharmony_ci .parse_monolithic = smb3_fs_context_parse_monolithic, 59762306a36Sopenharmony_ci .get_tree = smb3_get_tree, 59862306a36Sopenharmony_ci .reconfigure = smb3_reconfigure, 59962306a36Sopenharmony_ci}; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci/* 60262306a36Sopenharmony_ci * Parse a monolithic block of data from sys_mount(). 60362306a36Sopenharmony_ci * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data 60462306a36Sopenharmony_ci * @ctx: The superblock configuration to fill in. 60562306a36Sopenharmony_ci * @data: The data to parse 60662306a36Sopenharmony_ci * 60762306a36Sopenharmony_ci * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be 60862306a36Sopenharmony_ci * called from the ->monolithic_mount_data() fs_context operation. 60962306a36Sopenharmony_ci * 61062306a36Sopenharmony_ci * Returns 0 on success or the error returned by the ->parse_option() fs_context 61162306a36Sopenharmony_ci * operation on failure. 61262306a36Sopenharmony_ci */ 61362306a36Sopenharmony_cistatic int smb3_fs_context_parse_monolithic(struct fs_context *fc, 61462306a36Sopenharmony_ci void *data) 61562306a36Sopenharmony_ci{ 61662306a36Sopenharmony_ci char *options = data, *key; 61762306a36Sopenharmony_ci int ret = 0; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci if (!options) 62062306a36Sopenharmony_ci return 0; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci ret = security_sb_eat_lsm_opts(options, &fc->security); 62362306a36Sopenharmony_ci if (ret) 62462306a36Sopenharmony_ci return ret; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci /* BB Need to add support for sep= here TBD */ 62762306a36Sopenharmony_ci while ((key = strsep(&options, ",")) != NULL) { 62862306a36Sopenharmony_ci size_t len; 62962306a36Sopenharmony_ci char *value; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci if (*key == 0) 63262306a36Sopenharmony_ci break; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /* Check if following character is the deliminator If yes, 63562306a36Sopenharmony_ci * we have encountered a double deliminator reset the NULL 63662306a36Sopenharmony_ci * character to the deliminator 63762306a36Sopenharmony_ci */ 63862306a36Sopenharmony_ci while (options && options[0] == ',') { 63962306a36Sopenharmony_ci len = strlen(key); 64062306a36Sopenharmony_ci strcpy(key + len, options); 64162306a36Sopenharmony_ci options = strchr(options, ','); 64262306a36Sopenharmony_ci if (options) 64362306a36Sopenharmony_ci *options++ = 0; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci len = 0; 64862306a36Sopenharmony_ci value = strchr(key, '='); 64962306a36Sopenharmony_ci if (value) { 65062306a36Sopenharmony_ci if (value == key) 65162306a36Sopenharmony_ci continue; 65262306a36Sopenharmony_ci *value++ = 0; 65362306a36Sopenharmony_ci len = strlen(value); 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci ret = vfs_parse_fs_string(fc, key, value, len); 65762306a36Sopenharmony_ci if (ret < 0) 65862306a36Sopenharmony_ci break; 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci return ret; 66262306a36Sopenharmony_ci} 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci/* 66562306a36Sopenharmony_ci * Validate the preparsed information in the config. 66662306a36Sopenharmony_ci */ 66762306a36Sopenharmony_cistatic int smb3_fs_context_validate(struct fs_context *fc) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci struct smb3_fs_context *ctx = smb3_fc2context(fc); 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) { 67262306a36Sopenharmony_ci cifs_errorf(fc, "SMB Direct requires Version >=3.0\n"); 67362306a36Sopenharmony_ci return -EOPNOTSUPP; 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci#ifndef CONFIG_KEYS 67762306a36Sopenharmony_ci /* Muliuser mounts require CONFIG_KEYS support */ 67862306a36Sopenharmony_ci if (ctx->multiuser) { 67962306a36Sopenharmony_ci cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n"); 68062306a36Sopenharmony_ci return -1; 68162306a36Sopenharmony_ci } 68262306a36Sopenharmony_ci#endif 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci if (ctx->got_version == false) 68562306a36Sopenharmony_ci 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"); 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci if (!ctx->UNC) { 68962306a36Sopenharmony_ci cifs_errorf(fc, "CIFS mount error: No usable UNC path provided in device string!\n"); 69062306a36Sopenharmony_ci return -1; 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci /* make sure UNC has a share name */ 69462306a36Sopenharmony_ci if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) { 69562306a36Sopenharmony_ci cifs_errorf(fc, "Malformed UNC. Unable to find share name.\n"); 69662306a36Sopenharmony_ci return -ENOENT; 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci if (!ctx->got_ip) { 70062306a36Sopenharmony_ci int len; 70162306a36Sopenharmony_ci const char *slash; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci /* No ip= option specified? Try to get it from UNC */ 70462306a36Sopenharmony_ci /* Use the address part of the UNC. */ 70562306a36Sopenharmony_ci slash = strchr(&ctx->UNC[2], '\\'); 70662306a36Sopenharmony_ci len = slash - &ctx->UNC[2]; 70762306a36Sopenharmony_ci if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr, 70862306a36Sopenharmony_ci &ctx->UNC[2], len)) { 70962306a36Sopenharmony_ci pr_err("Unable to determine destination address\n"); 71062306a36Sopenharmony_ci return -EHOSTUNREACH; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci /* set the port that we got earlier */ 71562306a36Sopenharmony_ci cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci if (ctx->override_uid && !ctx->uid_specified) { 71862306a36Sopenharmony_ci ctx->override_uid = 0; 71962306a36Sopenharmony_ci pr_notice("ignoring forceuid mount option specified with no uid= option\n"); 72062306a36Sopenharmony_ci } 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci if (ctx->override_gid && !ctx->gid_specified) { 72362306a36Sopenharmony_ci ctx->override_gid = 0; 72462306a36Sopenharmony_ci pr_notice("ignoring forcegid mount option specified with no gid= option\n"); 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci return 0; 72862306a36Sopenharmony_ci} 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_cistatic int smb3_get_tree_common(struct fs_context *fc) 73162306a36Sopenharmony_ci{ 73262306a36Sopenharmony_ci struct smb3_fs_context *ctx = smb3_fc2context(fc); 73362306a36Sopenharmony_ci struct dentry *root; 73462306a36Sopenharmony_ci int rc = 0; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci root = cifs_smb3_do_mount(fc->fs_type, 0, ctx); 73762306a36Sopenharmony_ci if (IS_ERR(root)) 73862306a36Sopenharmony_ci return PTR_ERR(root); 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci fc->root = root; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci return rc; 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci/* 74662306a36Sopenharmony_ci * Create an SMB3 superblock from the parameters passed. 74762306a36Sopenharmony_ci */ 74862306a36Sopenharmony_cistatic int smb3_get_tree(struct fs_context *fc) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci int err = smb3_fs_context_validate(fc); 75162306a36Sopenharmony_ci int ret; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci if (err) 75462306a36Sopenharmony_ci return err; 75562306a36Sopenharmony_ci mutex_lock(&cifs_mount_mutex); 75662306a36Sopenharmony_ci ret = smb3_get_tree_common(fc); 75762306a36Sopenharmony_ci mutex_unlock(&cifs_mount_mutex); 75862306a36Sopenharmony_ci return ret; 75962306a36Sopenharmony_ci} 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_cistatic void smb3_fs_context_free(struct fs_context *fc) 76262306a36Sopenharmony_ci{ 76362306a36Sopenharmony_ci struct smb3_fs_context *ctx = smb3_fc2context(fc); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci smb3_cleanup_fs_context(ctx); 76662306a36Sopenharmony_ci} 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci/* 76962306a36Sopenharmony_ci * Compare the old and new proposed context during reconfigure 77062306a36Sopenharmony_ci * and check if the changes are compatible. 77162306a36Sopenharmony_ci */ 77262306a36Sopenharmony_cistatic int smb3_verify_reconfigure_ctx(struct fs_context *fc, 77362306a36Sopenharmony_ci struct smb3_fs_context *new_ctx, 77462306a36Sopenharmony_ci struct smb3_fs_context *old_ctx, bool need_recon) 77562306a36Sopenharmony_ci{ 77662306a36Sopenharmony_ci if (new_ctx->posix_paths != old_ctx->posix_paths) { 77762306a36Sopenharmony_ci cifs_errorf(fc, "can not change posixpaths during remount\n"); 77862306a36Sopenharmony_ci return -EINVAL; 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci if (new_ctx->sectype != old_ctx->sectype) { 78162306a36Sopenharmony_ci cifs_errorf(fc, "can not change sec during remount\n"); 78262306a36Sopenharmony_ci return -EINVAL; 78362306a36Sopenharmony_ci } 78462306a36Sopenharmony_ci if (new_ctx->multiuser != old_ctx->multiuser) { 78562306a36Sopenharmony_ci cifs_errorf(fc, "can not change multiuser during remount\n"); 78662306a36Sopenharmony_ci return -EINVAL; 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci if (new_ctx->UNC && 78962306a36Sopenharmony_ci (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) { 79062306a36Sopenharmony_ci cifs_errorf(fc, "can not change UNC during remount\n"); 79162306a36Sopenharmony_ci return -EINVAL; 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci if (new_ctx->username && 79462306a36Sopenharmony_ci (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) { 79562306a36Sopenharmony_ci cifs_errorf(fc, "can not change username during remount\n"); 79662306a36Sopenharmony_ci return -EINVAL; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci if (new_ctx->password && 79962306a36Sopenharmony_ci (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) { 80062306a36Sopenharmony_ci if (need_recon == false) { 80162306a36Sopenharmony_ci cifs_errorf(fc, 80262306a36Sopenharmony_ci "can not change password of active session during remount\n"); 80362306a36Sopenharmony_ci return -EINVAL; 80462306a36Sopenharmony_ci } else if (old_ctx->sectype == Kerberos) { 80562306a36Sopenharmony_ci cifs_errorf(fc, 80662306a36Sopenharmony_ci "can not change password for Kerberos via remount\n"); 80762306a36Sopenharmony_ci return -EINVAL; 80862306a36Sopenharmony_ci } 80962306a36Sopenharmony_ci } 81062306a36Sopenharmony_ci if (new_ctx->domainname && 81162306a36Sopenharmony_ci (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) { 81262306a36Sopenharmony_ci cifs_errorf(fc, "can not change domainname during remount\n"); 81362306a36Sopenharmony_ci return -EINVAL; 81462306a36Sopenharmony_ci } 81562306a36Sopenharmony_ci if (strcmp(new_ctx->workstation_name, old_ctx->workstation_name)) { 81662306a36Sopenharmony_ci cifs_errorf(fc, "can not change workstation_name during remount\n"); 81762306a36Sopenharmony_ci return -EINVAL; 81862306a36Sopenharmony_ci } 81962306a36Sopenharmony_ci if (new_ctx->nodename && 82062306a36Sopenharmony_ci (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) { 82162306a36Sopenharmony_ci cifs_errorf(fc, "can not change nodename during remount\n"); 82262306a36Sopenharmony_ci return -EINVAL; 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci if (new_ctx->iocharset && 82562306a36Sopenharmony_ci (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) { 82662306a36Sopenharmony_ci cifs_errorf(fc, "can not change iocharset during remount\n"); 82762306a36Sopenharmony_ci return -EINVAL; 82862306a36Sopenharmony_ci } 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci return 0; 83162306a36Sopenharmony_ci} 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci#define STEAL_STRING(cifs_sb, ctx, field) \ 83462306a36Sopenharmony_cido { \ 83562306a36Sopenharmony_ci kfree(ctx->field); \ 83662306a36Sopenharmony_ci ctx->field = cifs_sb->ctx->field; \ 83762306a36Sopenharmony_ci cifs_sb->ctx->field = NULL; \ 83862306a36Sopenharmony_ci} while (0) 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci#define STEAL_STRING_SENSITIVE(cifs_sb, ctx, field) \ 84162306a36Sopenharmony_cido { \ 84262306a36Sopenharmony_ci kfree_sensitive(ctx->field); \ 84362306a36Sopenharmony_ci ctx->field = cifs_sb->ctx->field; \ 84462306a36Sopenharmony_ci cifs_sb->ctx->field = NULL; \ 84562306a36Sopenharmony_ci} while (0) 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_cistatic int smb3_reconfigure(struct fs_context *fc) 84862306a36Sopenharmony_ci{ 84962306a36Sopenharmony_ci struct smb3_fs_context *ctx = smb3_fc2context(fc); 85062306a36Sopenharmony_ci struct dentry *root = fc->root; 85162306a36Sopenharmony_ci struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb); 85262306a36Sopenharmony_ci struct cifs_ses *ses = cifs_sb_master_tcon(cifs_sb)->ses; 85362306a36Sopenharmony_ci bool need_recon = false; 85462306a36Sopenharmony_ci int rc; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci if (ses->expired_pwd) 85762306a36Sopenharmony_ci need_recon = true; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx, need_recon); 86062306a36Sopenharmony_ci if (rc) 86162306a36Sopenharmony_ci return rc; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci /* 86462306a36Sopenharmony_ci * We can not change UNC/username/password/domainname/ 86562306a36Sopenharmony_ci * workstation_name/nodename/iocharset 86662306a36Sopenharmony_ci * during reconnect so ignore what we have in the new context and 86762306a36Sopenharmony_ci * just use what we already have in cifs_sb->ctx. 86862306a36Sopenharmony_ci */ 86962306a36Sopenharmony_ci STEAL_STRING(cifs_sb, ctx, UNC); 87062306a36Sopenharmony_ci STEAL_STRING(cifs_sb, ctx, source); 87162306a36Sopenharmony_ci STEAL_STRING(cifs_sb, ctx, username); 87262306a36Sopenharmony_ci if (need_recon == false) 87362306a36Sopenharmony_ci STEAL_STRING_SENSITIVE(cifs_sb, ctx, password); 87462306a36Sopenharmony_ci else { 87562306a36Sopenharmony_ci kfree_sensitive(ses->password); 87662306a36Sopenharmony_ci ses->password = kstrdup(ctx->password, GFP_KERNEL); 87762306a36Sopenharmony_ci } 87862306a36Sopenharmony_ci STEAL_STRING(cifs_sb, ctx, domainname); 87962306a36Sopenharmony_ci STEAL_STRING(cifs_sb, ctx, nodename); 88062306a36Sopenharmony_ci STEAL_STRING(cifs_sb, ctx, iocharset); 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci /* if rsize or wsize not passed in on remount, use previous values */ 88362306a36Sopenharmony_ci if (ctx->rsize == 0) 88462306a36Sopenharmony_ci ctx->rsize = cifs_sb->ctx->rsize; 88562306a36Sopenharmony_ci if (ctx->wsize == 0) 88662306a36Sopenharmony_ci ctx->wsize = cifs_sb->ctx->wsize; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci smb3_cleanup_fs_context_contents(cifs_sb->ctx); 89062306a36Sopenharmony_ci rc = smb3_fs_context_dup(cifs_sb->ctx, ctx); 89162306a36Sopenharmony_ci smb3_update_mnt_flags(cifs_sb); 89262306a36Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL 89362306a36Sopenharmony_ci if (!rc) 89462306a36Sopenharmony_ci rc = dfs_cache_remount_fs(cifs_sb); 89562306a36Sopenharmony_ci#endif 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci return rc; 89862306a36Sopenharmony_ci} 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_cistatic int smb3_fs_context_parse_param(struct fs_context *fc, 90162306a36Sopenharmony_ci struct fs_parameter *param) 90262306a36Sopenharmony_ci{ 90362306a36Sopenharmony_ci struct fs_parse_result result; 90462306a36Sopenharmony_ci struct smb3_fs_context *ctx = smb3_fc2context(fc); 90562306a36Sopenharmony_ci int i, opt; 90662306a36Sopenharmony_ci bool is_smb3 = !strcmp(fc->fs_type->name, "smb3"); 90762306a36Sopenharmony_ci bool skip_parsing = false; 90862306a36Sopenharmony_ci kuid_t uid; 90962306a36Sopenharmony_ci kgid_t gid; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci /* 91462306a36Sopenharmony_ci * fs_parse can not handle string options with an empty value so 91562306a36Sopenharmony_ci * we will need special handling of them. 91662306a36Sopenharmony_ci */ 91762306a36Sopenharmony_ci if (param->type == fs_value_is_string && param->string[0] == 0) { 91862306a36Sopenharmony_ci if (!strcmp("pass", param->key) || !strcmp("password", param->key)) { 91962306a36Sopenharmony_ci skip_parsing = true; 92062306a36Sopenharmony_ci opt = Opt_pass; 92162306a36Sopenharmony_ci } else if (!strcmp("user", param->key) || !strcmp("username", param->key)) { 92262306a36Sopenharmony_ci skip_parsing = true; 92362306a36Sopenharmony_ci opt = Opt_user; 92462306a36Sopenharmony_ci } 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci if (!skip_parsing) { 92862306a36Sopenharmony_ci opt = fs_parse(fc, smb3_fs_parameters, param, &result); 92962306a36Sopenharmony_ci if (opt < 0) 93062306a36Sopenharmony_ci return ctx->sloppy ? 1 : opt; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci switch (opt) { 93462306a36Sopenharmony_ci case Opt_compress: 93562306a36Sopenharmony_ci ctx->compression = UNKNOWN_TYPE; 93662306a36Sopenharmony_ci cifs_dbg(VFS, 93762306a36Sopenharmony_ci "SMB3 compression support is experimental\n"); 93862306a36Sopenharmony_ci break; 93962306a36Sopenharmony_ci case Opt_nodfs: 94062306a36Sopenharmony_ci ctx->nodfs = 1; 94162306a36Sopenharmony_ci break; 94262306a36Sopenharmony_ci case Opt_hard: 94362306a36Sopenharmony_ci if (result.negated) { 94462306a36Sopenharmony_ci if (ctx->retry == 1) 94562306a36Sopenharmony_ci cifs_dbg(VFS, "conflicting hard vs. soft mount options\n"); 94662306a36Sopenharmony_ci ctx->retry = 0; 94762306a36Sopenharmony_ci } else 94862306a36Sopenharmony_ci ctx->retry = 1; 94962306a36Sopenharmony_ci break; 95062306a36Sopenharmony_ci case Opt_soft: 95162306a36Sopenharmony_ci if (result.negated) 95262306a36Sopenharmony_ci ctx->retry = 1; 95362306a36Sopenharmony_ci else { 95462306a36Sopenharmony_ci if (ctx->retry == 1) 95562306a36Sopenharmony_ci cifs_dbg(VFS, "conflicting hard vs soft mount options\n"); 95662306a36Sopenharmony_ci ctx->retry = 0; 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci break; 95962306a36Sopenharmony_ci case Opt_mapposix: 96062306a36Sopenharmony_ci if (result.negated) 96162306a36Sopenharmony_ci ctx->remap = false; 96262306a36Sopenharmony_ci else { 96362306a36Sopenharmony_ci ctx->remap = true; 96462306a36Sopenharmony_ci ctx->sfu_remap = false; /* disable SFU mapping */ 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci break; 96762306a36Sopenharmony_ci case Opt_mapchars: 96862306a36Sopenharmony_ci if (result.negated) 96962306a36Sopenharmony_ci ctx->sfu_remap = false; 97062306a36Sopenharmony_ci else { 97162306a36Sopenharmony_ci ctx->sfu_remap = true; 97262306a36Sopenharmony_ci ctx->remap = false; /* disable SFM (mapposix) mapping */ 97362306a36Sopenharmony_ci } 97462306a36Sopenharmony_ci break; 97562306a36Sopenharmony_ci case Opt_user_xattr: 97662306a36Sopenharmony_ci if (result.negated) 97762306a36Sopenharmony_ci ctx->no_xattr = 1; 97862306a36Sopenharmony_ci else 97962306a36Sopenharmony_ci ctx->no_xattr = 0; 98062306a36Sopenharmony_ci break; 98162306a36Sopenharmony_ci case Opt_forceuid: 98262306a36Sopenharmony_ci if (result.negated) 98362306a36Sopenharmony_ci ctx->override_uid = 0; 98462306a36Sopenharmony_ci else 98562306a36Sopenharmony_ci ctx->override_uid = 1; 98662306a36Sopenharmony_ci break; 98762306a36Sopenharmony_ci case Opt_forcegid: 98862306a36Sopenharmony_ci if (result.negated) 98962306a36Sopenharmony_ci ctx->override_gid = 0; 99062306a36Sopenharmony_ci else 99162306a36Sopenharmony_ci ctx->override_gid = 1; 99262306a36Sopenharmony_ci break; 99362306a36Sopenharmony_ci case Opt_perm: 99462306a36Sopenharmony_ci if (result.negated) 99562306a36Sopenharmony_ci ctx->noperm = 1; 99662306a36Sopenharmony_ci else 99762306a36Sopenharmony_ci ctx->noperm = 0; 99862306a36Sopenharmony_ci break; 99962306a36Sopenharmony_ci case Opt_dynperm: 100062306a36Sopenharmony_ci if (result.negated) 100162306a36Sopenharmony_ci ctx->dynperm = 0; 100262306a36Sopenharmony_ci else 100362306a36Sopenharmony_ci ctx->dynperm = 1; 100462306a36Sopenharmony_ci break; 100562306a36Sopenharmony_ci case Opt_sfu: 100662306a36Sopenharmony_ci if (result.negated) 100762306a36Sopenharmony_ci ctx->sfu_emul = 0; 100862306a36Sopenharmony_ci else 100962306a36Sopenharmony_ci ctx->sfu_emul = 1; 101062306a36Sopenharmony_ci break; 101162306a36Sopenharmony_ci case Opt_noblocksend: 101262306a36Sopenharmony_ci ctx->noblocksnd = 1; 101362306a36Sopenharmony_ci break; 101462306a36Sopenharmony_ci case Opt_noautotune: 101562306a36Sopenharmony_ci ctx->noautotune = 1; 101662306a36Sopenharmony_ci break; 101762306a36Sopenharmony_ci case Opt_nolease: 101862306a36Sopenharmony_ci ctx->no_lease = 1; 101962306a36Sopenharmony_ci break; 102062306a36Sopenharmony_ci case Opt_nosparse: 102162306a36Sopenharmony_ci ctx->no_sparse = 1; 102262306a36Sopenharmony_ci break; 102362306a36Sopenharmony_ci case Opt_nodelete: 102462306a36Sopenharmony_ci ctx->nodelete = 1; 102562306a36Sopenharmony_ci break; 102662306a36Sopenharmony_ci case Opt_multichannel: 102762306a36Sopenharmony_ci if (result.negated) { 102862306a36Sopenharmony_ci ctx->multichannel = false; 102962306a36Sopenharmony_ci ctx->max_channels = 1; 103062306a36Sopenharmony_ci } else { 103162306a36Sopenharmony_ci ctx->multichannel = true; 103262306a36Sopenharmony_ci /* if number of channels not specified, default to 2 */ 103362306a36Sopenharmony_ci if (ctx->max_channels < 2) 103462306a36Sopenharmony_ci ctx->max_channels = 2; 103562306a36Sopenharmony_ci } 103662306a36Sopenharmony_ci break; 103762306a36Sopenharmony_ci case Opt_uid: 103862306a36Sopenharmony_ci uid = make_kuid(current_user_ns(), result.uint_32); 103962306a36Sopenharmony_ci if (!uid_valid(uid)) 104062306a36Sopenharmony_ci goto cifs_parse_mount_err; 104162306a36Sopenharmony_ci ctx->linux_uid = uid; 104262306a36Sopenharmony_ci ctx->uid_specified = true; 104362306a36Sopenharmony_ci break; 104462306a36Sopenharmony_ci case Opt_cruid: 104562306a36Sopenharmony_ci uid = make_kuid(current_user_ns(), result.uint_32); 104662306a36Sopenharmony_ci if (!uid_valid(uid)) 104762306a36Sopenharmony_ci goto cifs_parse_mount_err; 104862306a36Sopenharmony_ci ctx->cred_uid = uid; 104962306a36Sopenharmony_ci ctx->cruid_specified = true; 105062306a36Sopenharmony_ci break; 105162306a36Sopenharmony_ci case Opt_backupuid: 105262306a36Sopenharmony_ci uid = make_kuid(current_user_ns(), result.uint_32); 105362306a36Sopenharmony_ci if (!uid_valid(uid)) 105462306a36Sopenharmony_ci goto cifs_parse_mount_err; 105562306a36Sopenharmony_ci ctx->backupuid = uid; 105662306a36Sopenharmony_ci ctx->backupuid_specified = true; 105762306a36Sopenharmony_ci break; 105862306a36Sopenharmony_ci case Opt_backupgid: 105962306a36Sopenharmony_ci gid = make_kgid(current_user_ns(), result.uint_32); 106062306a36Sopenharmony_ci if (!gid_valid(gid)) 106162306a36Sopenharmony_ci goto cifs_parse_mount_err; 106262306a36Sopenharmony_ci ctx->backupgid = gid; 106362306a36Sopenharmony_ci ctx->backupgid_specified = true; 106462306a36Sopenharmony_ci break; 106562306a36Sopenharmony_ci case Opt_gid: 106662306a36Sopenharmony_ci gid = make_kgid(current_user_ns(), result.uint_32); 106762306a36Sopenharmony_ci if (!gid_valid(gid)) 106862306a36Sopenharmony_ci goto cifs_parse_mount_err; 106962306a36Sopenharmony_ci ctx->linux_gid = gid; 107062306a36Sopenharmony_ci ctx->gid_specified = true; 107162306a36Sopenharmony_ci break; 107262306a36Sopenharmony_ci case Opt_port: 107362306a36Sopenharmony_ci ctx->port = result.uint_32; 107462306a36Sopenharmony_ci break; 107562306a36Sopenharmony_ci case Opt_file_mode: 107662306a36Sopenharmony_ci ctx->file_mode = result.uint_32; 107762306a36Sopenharmony_ci break; 107862306a36Sopenharmony_ci case Opt_dirmode: 107962306a36Sopenharmony_ci ctx->dir_mode = result.uint_32; 108062306a36Sopenharmony_ci break; 108162306a36Sopenharmony_ci case Opt_min_enc_offload: 108262306a36Sopenharmony_ci ctx->min_offload = result.uint_32; 108362306a36Sopenharmony_ci break; 108462306a36Sopenharmony_ci case Opt_blocksize: 108562306a36Sopenharmony_ci /* 108662306a36Sopenharmony_ci * inode blocksize realistically should never need to be 108762306a36Sopenharmony_ci * less than 16K or greater than 16M and default is 1MB. 108862306a36Sopenharmony_ci * Note that small inode block sizes (e.g. 64K) can lead 108962306a36Sopenharmony_ci * to very poor performance of common tools like cp and scp 109062306a36Sopenharmony_ci */ 109162306a36Sopenharmony_ci if ((result.uint_32 < CIFS_MAX_MSGSIZE) || 109262306a36Sopenharmony_ci (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) { 109362306a36Sopenharmony_ci cifs_errorf(fc, "%s: Invalid blocksize\n", 109462306a36Sopenharmony_ci __func__); 109562306a36Sopenharmony_ci goto cifs_parse_mount_err; 109662306a36Sopenharmony_ci } 109762306a36Sopenharmony_ci ctx->bsize = result.uint_32; 109862306a36Sopenharmony_ci ctx->got_bsize = true; 109962306a36Sopenharmony_ci break; 110062306a36Sopenharmony_ci case Opt_rasize: 110162306a36Sopenharmony_ci /* 110262306a36Sopenharmony_ci * readahead size realistically should never need to be 110362306a36Sopenharmony_ci * less than 1M (CIFS_DEFAULT_IOSIZE) or greater than 32M 110462306a36Sopenharmony_ci * (perhaps an exception should be considered in the 110562306a36Sopenharmony_ci * for the case of a large number of channels 110662306a36Sopenharmony_ci * when multichannel is negotiated) since that would lead 110762306a36Sopenharmony_ci * to plenty of parallel I/O in flight to the server. 110862306a36Sopenharmony_ci * Note that smaller read ahead sizes would 110962306a36Sopenharmony_ci * hurt performance of common tools like cp and scp 111062306a36Sopenharmony_ci * which often trigger sequential i/o with read ahead 111162306a36Sopenharmony_ci */ 111262306a36Sopenharmony_ci if ((result.uint_32 > (8 * SMB3_DEFAULT_IOSIZE)) || 111362306a36Sopenharmony_ci (result.uint_32 < CIFS_DEFAULT_IOSIZE)) { 111462306a36Sopenharmony_ci cifs_errorf(fc, "%s: Invalid rasize %d vs. %d\n", 111562306a36Sopenharmony_ci __func__, result.uint_32, SMB3_DEFAULT_IOSIZE); 111662306a36Sopenharmony_ci goto cifs_parse_mount_err; 111762306a36Sopenharmony_ci } 111862306a36Sopenharmony_ci ctx->rasize = result.uint_32; 111962306a36Sopenharmony_ci break; 112062306a36Sopenharmony_ci case Opt_rsize: 112162306a36Sopenharmony_ci ctx->rsize = result.uint_32; 112262306a36Sopenharmony_ci ctx->got_rsize = true; 112362306a36Sopenharmony_ci break; 112462306a36Sopenharmony_ci case Opt_wsize: 112562306a36Sopenharmony_ci ctx->wsize = result.uint_32; 112662306a36Sopenharmony_ci ctx->got_wsize = true; 112762306a36Sopenharmony_ci if (ctx->wsize % PAGE_SIZE != 0) { 112862306a36Sopenharmony_ci ctx->wsize = round_down(ctx->wsize, PAGE_SIZE); 112962306a36Sopenharmony_ci if (ctx->wsize == 0) { 113062306a36Sopenharmony_ci ctx->wsize = PAGE_SIZE; 113162306a36Sopenharmony_ci cifs_dbg(VFS, "wsize too small, reset to minimum %ld\n", PAGE_SIZE); 113262306a36Sopenharmony_ci } else { 113362306a36Sopenharmony_ci cifs_dbg(VFS, 113462306a36Sopenharmony_ci "wsize rounded down to %d to multiple of PAGE_SIZE %ld\n", 113562306a36Sopenharmony_ci ctx->wsize, PAGE_SIZE); 113662306a36Sopenharmony_ci } 113762306a36Sopenharmony_ci } 113862306a36Sopenharmony_ci break; 113962306a36Sopenharmony_ci case Opt_acregmax: 114062306a36Sopenharmony_ci ctx->acregmax = HZ * result.uint_32; 114162306a36Sopenharmony_ci if (ctx->acregmax > CIFS_MAX_ACTIMEO) { 114262306a36Sopenharmony_ci cifs_errorf(fc, "acregmax too large\n"); 114362306a36Sopenharmony_ci goto cifs_parse_mount_err; 114462306a36Sopenharmony_ci } 114562306a36Sopenharmony_ci break; 114662306a36Sopenharmony_ci case Opt_acdirmax: 114762306a36Sopenharmony_ci ctx->acdirmax = HZ * result.uint_32; 114862306a36Sopenharmony_ci if (ctx->acdirmax > CIFS_MAX_ACTIMEO) { 114962306a36Sopenharmony_ci cifs_errorf(fc, "acdirmax too large\n"); 115062306a36Sopenharmony_ci goto cifs_parse_mount_err; 115162306a36Sopenharmony_ci } 115262306a36Sopenharmony_ci break; 115362306a36Sopenharmony_ci case Opt_actimeo: 115462306a36Sopenharmony_ci if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) { 115562306a36Sopenharmony_ci cifs_errorf(fc, "timeout too large\n"); 115662306a36Sopenharmony_ci goto cifs_parse_mount_err; 115762306a36Sopenharmony_ci } 115862306a36Sopenharmony_ci if ((ctx->acdirmax != CIFS_DEF_ACTIMEO) || 115962306a36Sopenharmony_ci (ctx->acregmax != CIFS_DEF_ACTIMEO)) { 116062306a36Sopenharmony_ci cifs_errorf(fc, "actimeo ignored since acregmax or acdirmax specified\n"); 116162306a36Sopenharmony_ci break; 116262306a36Sopenharmony_ci } 116362306a36Sopenharmony_ci ctx->acdirmax = ctx->acregmax = HZ * result.uint_32; 116462306a36Sopenharmony_ci break; 116562306a36Sopenharmony_ci case Opt_closetimeo: 116662306a36Sopenharmony_ci ctx->closetimeo = HZ * result.uint_32; 116762306a36Sopenharmony_ci if (ctx->closetimeo > SMB3_MAX_DCLOSETIMEO) { 116862306a36Sopenharmony_ci cifs_errorf(fc, "closetimeo too large\n"); 116962306a36Sopenharmony_ci goto cifs_parse_mount_err; 117062306a36Sopenharmony_ci } 117162306a36Sopenharmony_ci break; 117262306a36Sopenharmony_ci case Opt_echo_interval: 117362306a36Sopenharmony_ci ctx->echo_interval = result.uint_32; 117462306a36Sopenharmony_ci break; 117562306a36Sopenharmony_ci case Opt_snapshot: 117662306a36Sopenharmony_ci ctx->snapshot_time = result.uint_64; 117762306a36Sopenharmony_ci break; 117862306a36Sopenharmony_ci case Opt_max_credits: 117962306a36Sopenharmony_ci if (result.uint_32 < 20 || result.uint_32 > 60000) { 118062306a36Sopenharmony_ci cifs_errorf(fc, "%s: Invalid max_credits value\n", 118162306a36Sopenharmony_ci __func__); 118262306a36Sopenharmony_ci goto cifs_parse_mount_err; 118362306a36Sopenharmony_ci } 118462306a36Sopenharmony_ci ctx->max_credits = result.uint_32; 118562306a36Sopenharmony_ci break; 118662306a36Sopenharmony_ci case Opt_max_channels: 118762306a36Sopenharmony_ci if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) { 118862306a36Sopenharmony_ci cifs_errorf(fc, "%s: Invalid max_channels value, needs to be 1-%d\n", 118962306a36Sopenharmony_ci __func__, CIFS_MAX_CHANNELS); 119062306a36Sopenharmony_ci goto cifs_parse_mount_err; 119162306a36Sopenharmony_ci } 119262306a36Sopenharmony_ci ctx->max_channels = result.uint_32; 119362306a36Sopenharmony_ci /* If more than one channel requested ... they want multichan */ 119462306a36Sopenharmony_ci if (result.uint_32 > 1) 119562306a36Sopenharmony_ci ctx->multichannel = true; 119662306a36Sopenharmony_ci break; 119762306a36Sopenharmony_ci case Opt_max_cached_dirs: 119862306a36Sopenharmony_ci if (result.uint_32 < 1) { 119962306a36Sopenharmony_ci cifs_errorf(fc, "%s: Invalid max_cached_dirs, needs to be 1 or more\n", 120062306a36Sopenharmony_ci __func__); 120162306a36Sopenharmony_ci goto cifs_parse_mount_err; 120262306a36Sopenharmony_ci } 120362306a36Sopenharmony_ci ctx->max_cached_dirs = result.uint_32; 120462306a36Sopenharmony_ci break; 120562306a36Sopenharmony_ci case Opt_handletimeout: 120662306a36Sopenharmony_ci ctx->handle_timeout = result.uint_32; 120762306a36Sopenharmony_ci if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) { 120862306a36Sopenharmony_ci cifs_errorf(fc, "Invalid handle cache timeout, longer than 16 minutes\n"); 120962306a36Sopenharmony_ci goto cifs_parse_mount_err; 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci break; 121262306a36Sopenharmony_ci case Opt_source: 121362306a36Sopenharmony_ci kfree(ctx->UNC); 121462306a36Sopenharmony_ci ctx->UNC = NULL; 121562306a36Sopenharmony_ci switch (smb3_parse_devname(param->string, ctx)) { 121662306a36Sopenharmony_ci case 0: 121762306a36Sopenharmony_ci break; 121862306a36Sopenharmony_ci case -ENOMEM: 121962306a36Sopenharmony_ci cifs_errorf(fc, "Unable to allocate memory for devname\n"); 122062306a36Sopenharmony_ci goto cifs_parse_mount_err; 122162306a36Sopenharmony_ci case -EINVAL: 122262306a36Sopenharmony_ci cifs_errorf(fc, "Malformed UNC in devname\n"); 122362306a36Sopenharmony_ci goto cifs_parse_mount_err; 122462306a36Sopenharmony_ci default: 122562306a36Sopenharmony_ci cifs_errorf(fc, "Unknown error parsing devname\n"); 122662306a36Sopenharmony_ci goto cifs_parse_mount_err; 122762306a36Sopenharmony_ci } 122862306a36Sopenharmony_ci ctx->source = smb3_fs_context_fullpath(ctx, '/'); 122962306a36Sopenharmony_ci if (IS_ERR(ctx->source)) { 123062306a36Sopenharmony_ci ctx->source = NULL; 123162306a36Sopenharmony_ci cifs_errorf(fc, "OOM when copying UNC string\n"); 123262306a36Sopenharmony_ci goto cifs_parse_mount_err; 123362306a36Sopenharmony_ci } 123462306a36Sopenharmony_ci fc->source = kstrdup(ctx->source, GFP_KERNEL); 123562306a36Sopenharmony_ci if (fc->source == NULL) { 123662306a36Sopenharmony_ci cifs_errorf(fc, "OOM when copying UNC string\n"); 123762306a36Sopenharmony_ci goto cifs_parse_mount_err; 123862306a36Sopenharmony_ci } 123962306a36Sopenharmony_ci break; 124062306a36Sopenharmony_ci case Opt_user: 124162306a36Sopenharmony_ci kfree(ctx->username); 124262306a36Sopenharmony_ci ctx->username = NULL; 124362306a36Sopenharmony_ci if (ctx->nullauth) 124462306a36Sopenharmony_ci break; 124562306a36Sopenharmony_ci if (strlen(param->string) == 0) { 124662306a36Sopenharmony_ci /* null user, ie. anonymous authentication */ 124762306a36Sopenharmony_ci ctx->nullauth = 1; 124862306a36Sopenharmony_ci break; 124962306a36Sopenharmony_ci } 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) > 125262306a36Sopenharmony_ci CIFS_MAX_USERNAME_LEN) { 125362306a36Sopenharmony_ci pr_warn("username too long\n"); 125462306a36Sopenharmony_ci goto cifs_parse_mount_err; 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci ctx->username = kstrdup(param->string, GFP_KERNEL); 125762306a36Sopenharmony_ci if (ctx->username == NULL) { 125862306a36Sopenharmony_ci cifs_errorf(fc, "OOM when copying username string\n"); 125962306a36Sopenharmony_ci goto cifs_parse_mount_err; 126062306a36Sopenharmony_ci } 126162306a36Sopenharmony_ci break; 126262306a36Sopenharmony_ci case Opt_pass: 126362306a36Sopenharmony_ci kfree_sensitive(ctx->password); 126462306a36Sopenharmony_ci ctx->password = NULL; 126562306a36Sopenharmony_ci if (strlen(param->string) == 0) 126662306a36Sopenharmony_ci break; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci ctx->password = kstrdup(param->string, GFP_KERNEL); 126962306a36Sopenharmony_ci if (ctx->password == NULL) { 127062306a36Sopenharmony_ci cifs_errorf(fc, "OOM when copying password string\n"); 127162306a36Sopenharmony_ci goto cifs_parse_mount_err; 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci break; 127462306a36Sopenharmony_ci case Opt_ip: 127562306a36Sopenharmony_ci if (strlen(param->string) == 0) { 127662306a36Sopenharmony_ci ctx->got_ip = false; 127762306a36Sopenharmony_ci break; 127862306a36Sopenharmony_ci } 127962306a36Sopenharmony_ci if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr, 128062306a36Sopenharmony_ci param->string, 128162306a36Sopenharmony_ci strlen(param->string))) { 128262306a36Sopenharmony_ci pr_err("bad ip= option (%s)\n", param->string); 128362306a36Sopenharmony_ci goto cifs_parse_mount_err; 128462306a36Sopenharmony_ci } 128562306a36Sopenharmony_ci ctx->got_ip = true; 128662306a36Sopenharmony_ci break; 128762306a36Sopenharmony_ci case Opt_domain: 128862306a36Sopenharmony_ci if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN) 128962306a36Sopenharmony_ci == CIFS_MAX_DOMAINNAME_LEN) { 129062306a36Sopenharmony_ci pr_warn("domain name too long\n"); 129162306a36Sopenharmony_ci goto cifs_parse_mount_err; 129262306a36Sopenharmony_ci } 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci kfree(ctx->domainname); 129562306a36Sopenharmony_ci ctx->domainname = kstrdup(param->string, GFP_KERNEL); 129662306a36Sopenharmony_ci if (ctx->domainname == NULL) { 129762306a36Sopenharmony_ci cifs_errorf(fc, "OOM when copying domainname string\n"); 129862306a36Sopenharmony_ci goto cifs_parse_mount_err; 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci cifs_dbg(FYI, "Domain name set\n"); 130162306a36Sopenharmony_ci break; 130262306a36Sopenharmony_ci case Opt_srcaddr: 130362306a36Sopenharmony_ci if (!cifs_convert_address( 130462306a36Sopenharmony_ci (struct sockaddr *)&ctx->srcaddr, 130562306a36Sopenharmony_ci param->string, strlen(param->string))) { 130662306a36Sopenharmony_ci pr_warn("Could not parse srcaddr: %s\n", 130762306a36Sopenharmony_ci param->string); 130862306a36Sopenharmony_ci goto cifs_parse_mount_err; 130962306a36Sopenharmony_ci } 131062306a36Sopenharmony_ci break; 131162306a36Sopenharmony_ci case Opt_iocharset: 131262306a36Sopenharmony_ci if (strnlen(param->string, 1024) >= 65) { 131362306a36Sopenharmony_ci pr_warn("iocharset name too long\n"); 131462306a36Sopenharmony_ci goto cifs_parse_mount_err; 131562306a36Sopenharmony_ci } 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci if (strncasecmp(param->string, "default", 7) != 0) { 131862306a36Sopenharmony_ci kfree(ctx->iocharset); 131962306a36Sopenharmony_ci ctx->iocharset = kstrdup(param->string, GFP_KERNEL); 132062306a36Sopenharmony_ci if (ctx->iocharset == NULL) { 132162306a36Sopenharmony_ci cifs_errorf(fc, "OOM when copying iocharset string\n"); 132262306a36Sopenharmony_ci goto cifs_parse_mount_err; 132362306a36Sopenharmony_ci } 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci /* if iocharset not set then load_nls_default 132662306a36Sopenharmony_ci * is used by caller 132762306a36Sopenharmony_ci */ 132862306a36Sopenharmony_ci cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset); 132962306a36Sopenharmony_ci break; 133062306a36Sopenharmony_ci case Opt_netbiosname: 133162306a36Sopenharmony_ci memset(ctx->source_rfc1001_name, 0x20, 133262306a36Sopenharmony_ci RFC1001_NAME_LEN); 133362306a36Sopenharmony_ci /* 133462306a36Sopenharmony_ci * FIXME: are there cases in which a comma can 133562306a36Sopenharmony_ci * be valid in workstation netbios name (and 133662306a36Sopenharmony_ci * need special handling)? 133762306a36Sopenharmony_ci */ 133862306a36Sopenharmony_ci for (i = 0; i < RFC1001_NAME_LEN; i++) { 133962306a36Sopenharmony_ci /* don't ucase netbiosname for user */ 134062306a36Sopenharmony_ci if (param->string[i] == 0) 134162306a36Sopenharmony_ci break; 134262306a36Sopenharmony_ci ctx->source_rfc1001_name[i] = param->string[i]; 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci /* The string has 16th byte zero still from 134562306a36Sopenharmony_ci * set at top of the function 134662306a36Sopenharmony_ci */ 134762306a36Sopenharmony_ci if (i == RFC1001_NAME_LEN && param->string[i] != 0) 134862306a36Sopenharmony_ci pr_warn("netbiosname longer than 15 truncated\n"); 134962306a36Sopenharmony_ci break; 135062306a36Sopenharmony_ci case Opt_servern: 135162306a36Sopenharmony_ci /* last byte, type, is 0x20 for servr type */ 135262306a36Sopenharmony_ci memset(ctx->target_rfc1001_name, 0x20, 135362306a36Sopenharmony_ci RFC1001_NAME_LEN_WITH_NULL); 135462306a36Sopenharmony_ci /* 135562306a36Sopenharmony_ci * BB are there cases in which a comma can be valid in this 135662306a36Sopenharmony_ci * workstation netbios name (and need special handling)? 135762306a36Sopenharmony_ci */ 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci /* user or mount helper must uppercase the netbios name */ 136062306a36Sopenharmony_ci for (i = 0; i < 15; i++) { 136162306a36Sopenharmony_ci if (param->string[i] == 0) 136262306a36Sopenharmony_ci break; 136362306a36Sopenharmony_ci ctx->target_rfc1001_name[i] = param->string[i]; 136462306a36Sopenharmony_ci } 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci /* The string has 16th byte zero still from set at top of function */ 136762306a36Sopenharmony_ci if (i == RFC1001_NAME_LEN && param->string[i] != 0) 136862306a36Sopenharmony_ci pr_warn("server netbiosname longer than 15 truncated\n"); 136962306a36Sopenharmony_ci break; 137062306a36Sopenharmony_ci case Opt_ver: 137162306a36Sopenharmony_ci /* version of mount userspace tools, not dialect */ 137262306a36Sopenharmony_ci /* If interface changes in mount.cifs bump to new ver */ 137362306a36Sopenharmony_ci if (strncasecmp(param->string, "1", 1) == 0) { 137462306a36Sopenharmony_ci if (strlen(param->string) > 1) { 137562306a36Sopenharmony_ci pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n", 137662306a36Sopenharmony_ci param->string); 137762306a36Sopenharmony_ci goto cifs_parse_mount_err; 137862306a36Sopenharmony_ci } 137962306a36Sopenharmony_ci /* This is the default */ 138062306a36Sopenharmony_ci break; 138162306a36Sopenharmony_ci } 138262306a36Sopenharmony_ci /* For all other value, error */ 138362306a36Sopenharmony_ci pr_warn("Invalid mount helper version specified\n"); 138462306a36Sopenharmony_ci goto cifs_parse_mount_err; 138562306a36Sopenharmony_ci case Opt_vers: 138662306a36Sopenharmony_ci /* protocol version (dialect) */ 138762306a36Sopenharmony_ci if (cifs_parse_smb_version(fc, param->string, ctx, is_smb3) != 0) 138862306a36Sopenharmony_ci goto cifs_parse_mount_err; 138962306a36Sopenharmony_ci ctx->got_version = true; 139062306a36Sopenharmony_ci break; 139162306a36Sopenharmony_ci case Opt_sec: 139262306a36Sopenharmony_ci if (cifs_parse_security_flavors(fc, param->string, ctx) != 0) 139362306a36Sopenharmony_ci goto cifs_parse_mount_err; 139462306a36Sopenharmony_ci break; 139562306a36Sopenharmony_ci case Opt_cache: 139662306a36Sopenharmony_ci if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0) 139762306a36Sopenharmony_ci goto cifs_parse_mount_err; 139862306a36Sopenharmony_ci break; 139962306a36Sopenharmony_ci case Opt_witness: 140062306a36Sopenharmony_ci#ifndef CONFIG_CIFS_SWN_UPCALL 140162306a36Sopenharmony_ci cifs_errorf(fc, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n"); 140262306a36Sopenharmony_ci goto cifs_parse_mount_err; 140362306a36Sopenharmony_ci#endif 140462306a36Sopenharmony_ci ctx->witness = true; 140562306a36Sopenharmony_ci pr_warn_once("Witness protocol support is experimental\n"); 140662306a36Sopenharmony_ci break; 140762306a36Sopenharmony_ci case Opt_rootfs: 140862306a36Sopenharmony_ci#ifndef CONFIG_CIFS_ROOT 140962306a36Sopenharmony_ci cifs_dbg(VFS, "rootfs support requires CONFIG_CIFS_ROOT config option\n"); 141062306a36Sopenharmony_ci goto cifs_parse_mount_err; 141162306a36Sopenharmony_ci#endif 141262306a36Sopenharmony_ci ctx->rootfs = true; 141362306a36Sopenharmony_ci break; 141462306a36Sopenharmony_ci case Opt_posixpaths: 141562306a36Sopenharmony_ci if (result.negated) 141662306a36Sopenharmony_ci ctx->posix_paths = 0; 141762306a36Sopenharmony_ci else 141862306a36Sopenharmony_ci ctx->posix_paths = 1; 141962306a36Sopenharmony_ci break; 142062306a36Sopenharmony_ci case Opt_unix: 142162306a36Sopenharmony_ci if (result.negated) { 142262306a36Sopenharmony_ci if (ctx->linux_ext == 1) 142362306a36Sopenharmony_ci pr_warn_once("conflicting posix mount options specified\n"); 142462306a36Sopenharmony_ci ctx->linux_ext = 0; 142562306a36Sopenharmony_ci ctx->no_linux_ext = 1; 142662306a36Sopenharmony_ci } else { 142762306a36Sopenharmony_ci if (ctx->no_linux_ext == 1) 142862306a36Sopenharmony_ci pr_warn_once("conflicting posix mount options specified\n"); 142962306a36Sopenharmony_ci ctx->linux_ext = 1; 143062306a36Sopenharmony_ci ctx->no_linux_ext = 0; 143162306a36Sopenharmony_ci } 143262306a36Sopenharmony_ci break; 143362306a36Sopenharmony_ci case Opt_nocase: 143462306a36Sopenharmony_ci ctx->nocase = 1; 143562306a36Sopenharmony_ci break; 143662306a36Sopenharmony_ci case Opt_brl: 143762306a36Sopenharmony_ci if (result.negated) { 143862306a36Sopenharmony_ci /* 143962306a36Sopenharmony_ci * turn off mandatory locking in mode 144062306a36Sopenharmony_ci * if remote locking is turned off since the 144162306a36Sopenharmony_ci * local vfs will do advisory 144262306a36Sopenharmony_ci */ 144362306a36Sopenharmony_ci if (ctx->file_mode == 144462306a36Sopenharmony_ci (S_IALLUGO & ~(S_ISUID | S_IXGRP))) 144562306a36Sopenharmony_ci ctx->file_mode = S_IALLUGO; 144662306a36Sopenharmony_ci ctx->nobrl = 1; 144762306a36Sopenharmony_ci } else 144862306a36Sopenharmony_ci ctx->nobrl = 0; 144962306a36Sopenharmony_ci break; 145062306a36Sopenharmony_ci case Opt_handlecache: 145162306a36Sopenharmony_ci if (result.negated) 145262306a36Sopenharmony_ci ctx->nohandlecache = 1; 145362306a36Sopenharmony_ci else 145462306a36Sopenharmony_ci ctx->nohandlecache = 0; 145562306a36Sopenharmony_ci break; 145662306a36Sopenharmony_ci case Opt_forcemandatorylock: 145762306a36Sopenharmony_ci ctx->mand_lock = 1; 145862306a36Sopenharmony_ci break; 145962306a36Sopenharmony_ci case Opt_setuids: 146062306a36Sopenharmony_ci ctx->setuids = result.negated; 146162306a36Sopenharmony_ci break; 146262306a36Sopenharmony_ci case Opt_intr: 146362306a36Sopenharmony_ci ctx->intr = !result.negated; 146462306a36Sopenharmony_ci break; 146562306a36Sopenharmony_ci case Opt_setuidfromacl: 146662306a36Sopenharmony_ci ctx->setuidfromacl = 1; 146762306a36Sopenharmony_ci break; 146862306a36Sopenharmony_ci case Opt_strictsync: 146962306a36Sopenharmony_ci ctx->nostrictsync = result.negated; 147062306a36Sopenharmony_ci break; 147162306a36Sopenharmony_ci case Opt_serverino: 147262306a36Sopenharmony_ci ctx->server_ino = !result.negated; 147362306a36Sopenharmony_ci break; 147462306a36Sopenharmony_ci case Opt_rwpidforward: 147562306a36Sopenharmony_ci ctx->rwpidforward = 1; 147662306a36Sopenharmony_ci break; 147762306a36Sopenharmony_ci case Opt_modesid: 147862306a36Sopenharmony_ci ctx->mode_ace = 1; 147962306a36Sopenharmony_ci break; 148062306a36Sopenharmony_ci case Opt_cifsacl: 148162306a36Sopenharmony_ci ctx->cifs_acl = !result.negated; 148262306a36Sopenharmony_ci break; 148362306a36Sopenharmony_ci case Opt_acl: 148462306a36Sopenharmony_ci ctx->no_psx_acl = result.negated; 148562306a36Sopenharmony_ci break; 148662306a36Sopenharmony_ci case Opt_locallease: 148762306a36Sopenharmony_ci ctx->local_lease = 1; 148862306a36Sopenharmony_ci break; 148962306a36Sopenharmony_ci case Opt_sign: 149062306a36Sopenharmony_ci ctx->sign = true; 149162306a36Sopenharmony_ci break; 149262306a36Sopenharmony_ci case Opt_ignore_signature: 149362306a36Sopenharmony_ci ctx->sign = true; 149462306a36Sopenharmony_ci ctx->ignore_signature = true; 149562306a36Sopenharmony_ci break; 149662306a36Sopenharmony_ci case Opt_seal: 149762306a36Sopenharmony_ci /* we do not do the following in secFlags because seal 149862306a36Sopenharmony_ci * is a per tree connection (mount) not a per socket 149962306a36Sopenharmony_ci * or per-smb connection option in the protocol 150062306a36Sopenharmony_ci * vol->secFlg |= CIFSSEC_MUST_SEAL; 150162306a36Sopenharmony_ci */ 150262306a36Sopenharmony_ci ctx->seal = 1; 150362306a36Sopenharmony_ci break; 150462306a36Sopenharmony_ci case Opt_noac: 150562306a36Sopenharmony_ci pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n"); 150662306a36Sopenharmony_ci break; 150762306a36Sopenharmony_ci case Opt_fsc: 150862306a36Sopenharmony_ci#ifndef CONFIG_CIFS_FSCACHE 150962306a36Sopenharmony_ci cifs_errorf(fc, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n"); 151062306a36Sopenharmony_ci goto cifs_parse_mount_err; 151162306a36Sopenharmony_ci#endif 151262306a36Sopenharmony_ci ctx->fsc = true; 151362306a36Sopenharmony_ci break; 151462306a36Sopenharmony_ci case Opt_mfsymlinks: 151562306a36Sopenharmony_ci ctx->mfsymlinks = true; 151662306a36Sopenharmony_ci break; 151762306a36Sopenharmony_ci case Opt_multiuser: 151862306a36Sopenharmony_ci ctx->multiuser = true; 151962306a36Sopenharmony_ci break; 152062306a36Sopenharmony_ci case Opt_sloppy: 152162306a36Sopenharmony_ci ctx->sloppy = true; 152262306a36Sopenharmony_ci break; 152362306a36Sopenharmony_ci case Opt_nosharesock: 152462306a36Sopenharmony_ci ctx->nosharesock = true; 152562306a36Sopenharmony_ci break; 152662306a36Sopenharmony_ci case Opt_persistent: 152762306a36Sopenharmony_ci if (result.negated) { 152862306a36Sopenharmony_ci ctx->nopersistent = true; 152962306a36Sopenharmony_ci if (ctx->persistent) { 153062306a36Sopenharmony_ci cifs_errorf(fc, "persistenthandles mount options conflict\n"); 153162306a36Sopenharmony_ci goto cifs_parse_mount_err; 153262306a36Sopenharmony_ci } 153362306a36Sopenharmony_ci } else { 153462306a36Sopenharmony_ci ctx->persistent = true; 153562306a36Sopenharmony_ci if ((ctx->nopersistent) || (ctx->resilient)) { 153662306a36Sopenharmony_ci cifs_errorf(fc, "persistenthandles mount options conflict\n"); 153762306a36Sopenharmony_ci goto cifs_parse_mount_err; 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci } 154062306a36Sopenharmony_ci break; 154162306a36Sopenharmony_ci case Opt_resilient: 154262306a36Sopenharmony_ci if (result.negated) { 154362306a36Sopenharmony_ci ctx->resilient = false; /* already the default */ 154462306a36Sopenharmony_ci } else { 154562306a36Sopenharmony_ci ctx->resilient = true; 154662306a36Sopenharmony_ci if (ctx->persistent) { 154762306a36Sopenharmony_ci cifs_errorf(fc, "persistenthandles mount options conflict\n"); 154862306a36Sopenharmony_ci goto cifs_parse_mount_err; 154962306a36Sopenharmony_ci } 155062306a36Sopenharmony_ci } 155162306a36Sopenharmony_ci break; 155262306a36Sopenharmony_ci case Opt_tcp_nodelay: 155362306a36Sopenharmony_ci /* tcp nodelay should not usually be needed since we CORK/UNCORK the socket */ 155462306a36Sopenharmony_ci if (result.negated) 155562306a36Sopenharmony_ci ctx->sockopt_tcp_nodelay = false; 155662306a36Sopenharmony_ci else 155762306a36Sopenharmony_ci ctx->sockopt_tcp_nodelay = true; 155862306a36Sopenharmony_ci break; 155962306a36Sopenharmony_ci case Opt_domainauto: 156062306a36Sopenharmony_ci ctx->domainauto = true; 156162306a36Sopenharmony_ci break; 156262306a36Sopenharmony_ci case Opt_rdma: 156362306a36Sopenharmony_ci ctx->rdma = true; 156462306a36Sopenharmony_ci break; 156562306a36Sopenharmony_ci } 156662306a36Sopenharmony_ci /* case Opt_ignore: - is ignored as expected ... */ 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci return 0; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci cifs_parse_mount_err: 157162306a36Sopenharmony_ci kfree_sensitive(ctx->password); 157262306a36Sopenharmony_ci ctx->password = NULL; 157362306a36Sopenharmony_ci return -EINVAL; 157462306a36Sopenharmony_ci} 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ciint smb3_init_fs_context(struct fs_context *fc) 157762306a36Sopenharmony_ci{ 157862306a36Sopenharmony_ci struct smb3_fs_context *ctx; 157962306a36Sopenharmony_ci char *nodename = utsname()->nodename; 158062306a36Sopenharmony_ci int i; 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL); 158362306a36Sopenharmony_ci if (unlikely(!ctx)) 158462306a36Sopenharmony_ci return -ENOMEM; 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci strscpy(ctx->workstation_name, nodename, sizeof(ctx->workstation_name)); 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci /* 158962306a36Sopenharmony_ci * does not have to be perfect mapping since field is 159062306a36Sopenharmony_ci * informational, only used for servers that do not support 159162306a36Sopenharmony_ci * port 445 and it can be overridden at mount time 159262306a36Sopenharmony_ci */ 159362306a36Sopenharmony_ci memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN); 159462306a36Sopenharmony_ci for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++) 159562306a36Sopenharmony_ci ctx->source_rfc1001_name[i] = toupper(nodename[i]); 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0; 159862306a36Sopenharmony_ci /* 159962306a36Sopenharmony_ci * null target name indicates to use *SMBSERVR default called name 160062306a36Sopenharmony_ci * if we end up sending RFC1001 session initialize 160162306a36Sopenharmony_ci */ 160262306a36Sopenharmony_ci ctx->target_rfc1001_name[0] = 0; 160362306a36Sopenharmony_ci ctx->cred_uid = current_uid(); 160462306a36Sopenharmony_ci ctx->linux_uid = current_uid(); 160562306a36Sopenharmony_ci ctx->linux_gid = current_gid(); 160662306a36Sopenharmony_ci /* By default 4MB read ahead size, 1MB block size */ 160762306a36Sopenharmony_ci ctx->bsize = CIFS_DEFAULT_IOSIZE; /* can improve cp performance significantly */ 160862306a36Sopenharmony_ci ctx->rasize = 0; /* 0 = use default (ie negotiated rsize) for read ahead pages */ 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_ci /* 161162306a36Sopenharmony_ci * default to SFM style remapping of seven reserved characters 161262306a36Sopenharmony_ci * unless user overrides it or we negotiate CIFS POSIX where 161362306a36Sopenharmony_ci * it is unnecessary. Can not simultaneously use more than one mapping 161462306a36Sopenharmony_ci * since then readdir could list files that open could not open 161562306a36Sopenharmony_ci */ 161662306a36Sopenharmony_ci ctx->remap = true; 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci /* default to only allowing write access to owner of the mount */ 161962306a36Sopenharmony_ci ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 162262306a36Sopenharmony_ci /* default is always to request posix paths. */ 162362306a36Sopenharmony_ci ctx->posix_paths = 1; 162462306a36Sopenharmony_ci /* default to using server inode numbers where available */ 162562306a36Sopenharmony_ci ctx->server_ino = 1; 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci /* default is to use strict cifs caching semantics */ 162862306a36Sopenharmony_ci ctx->strict_io = true; 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci ctx->acregmax = CIFS_DEF_ACTIMEO; 163162306a36Sopenharmony_ci ctx->acdirmax = CIFS_DEF_ACTIMEO; 163262306a36Sopenharmony_ci ctx->closetimeo = SMB3_DEF_DCLOSETIMEO; 163362306a36Sopenharmony_ci ctx->max_cached_dirs = MAX_CACHED_FIDS; 163462306a36Sopenharmony_ci /* Most clients set timeout to 0, allows server to use its default */ 163562306a36Sopenharmony_ci ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */ 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */ 163862306a36Sopenharmony_ci ctx->ops = &smb30_operations; 163962306a36Sopenharmony_ci ctx->vals = &smbdefault_values; 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT; 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci /* default to no multichannel (single server connection) */ 164462306a36Sopenharmony_ci ctx->multichannel = false; 164562306a36Sopenharmony_ci ctx->max_channels = 1; 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci ctx->backupuid_specified = false; /* no backup intent for a user */ 164862306a36Sopenharmony_ci ctx->backupgid_specified = false; /* no backup intent for a group */ 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci/* 165162306a36Sopenharmony_ci * short int override_uid = -1; 165262306a36Sopenharmony_ci * short int override_gid = -1; 165362306a36Sopenharmony_ci * char *nodename = strdup(utsname()->nodename); 165462306a36Sopenharmony_ci * struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr; 165562306a36Sopenharmony_ci */ 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci fc->fs_private = ctx; 165862306a36Sopenharmony_ci fc->ops = &smb3_fs_context_ops; 165962306a36Sopenharmony_ci return 0; 166062306a36Sopenharmony_ci} 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_civoid 166362306a36Sopenharmony_cismb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx) 166462306a36Sopenharmony_ci{ 166562306a36Sopenharmony_ci if (ctx == NULL) 166662306a36Sopenharmony_ci return; 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci /* 166962306a36Sopenharmony_ci * Make sure this stays in sync with smb3_fs_context_dup() 167062306a36Sopenharmony_ci */ 167162306a36Sopenharmony_ci kfree(ctx->username); 167262306a36Sopenharmony_ci ctx->username = NULL; 167362306a36Sopenharmony_ci kfree_sensitive(ctx->password); 167462306a36Sopenharmony_ci ctx->password = NULL; 167562306a36Sopenharmony_ci kfree(ctx->server_hostname); 167662306a36Sopenharmony_ci ctx->server_hostname = NULL; 167762306a36Sopenharmony_ci kfree(ctx->UNC); 167862306a36Sopenharmony_ci ctx->UNC = NULL; 167962306a36Sopenharmony_ci kfree(ctx->source); 168062306a36Sopenharmony_ci ctx->source = NULL; 168162306a36Sopenharmony_ci kfree(ctx->domainname); 168262306a36Sopenharmony_ci ctx->domainname = NULL; 168362306a36Sopenharmony_ci kfree(ctx->nodename); 168462306a36Sopenharmony_ci ctx->nodename = NULL; 168562306a36Sopenharmony_ci kfree(ctx->iocharset); 168662306a36Sopenharmony_ci ctx->iocharset = NULL; 168762306a36Sopenharmony_ci kfree(ctx->prepath); 168862306a36Sopenharmony_ci ctx->prepath = NULL; 168962306a36Sopenharmony_ci kfree(ctx->leaf_fullpath); 169062306a36Sopenharmony_ci ctx->leaf_fullpath = NULL; 169162306a36Sopenharmony_ci} 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_civoid 169462306a36Sopenharmony_cismb3_cleanup_fs_context(struct smb3_fs_context *ctx) 169562306a36Sopenharmony_ci{ 169662306a36Sopenharmony_ci if (!ctx) 169762306a36Sopenharmony_ci return; 169862306a36Sopenharmony_ci smb3_cleanup_fs_context_contents(ctx); 169962306a36Sopenharmony_ci kfree(ctx); 170062306a36Sopenharmony_ci} 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_civoid smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb) 170362306a36Sopenharmony_ci{ 170462306a36Sopenharmony_ci struct smb3_fs_context *ctx = cifs_sb->ctx; 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci if (ctx->nodfs) 170762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS; 170862306a36Sopenharmony_ci else 170962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS; 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci if (ctx->noperm) 171262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; 171362306a36Sopenharmony_ci else 171462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM; 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci if (ctx->setuids) 171762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; 171862306a36Sopenharmony_ci else 171962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID; 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci if (ctx->setuidfromacl) 172262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL; 172362306a36Sopenharmony_ci else 172462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL; 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci if (ctx->server_ino) 172762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; 172862306a36Sopenharmony_ci else 172962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci if (ctx->remap) 173262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR; 173362306a36Sopenharmony_ci else 173462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR; 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci if (ctx->sfu_remap) 173762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; 173862306a36Sopenharmony_ci else 173962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR; 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci if (ctx->no_xattr) 174262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; 174362306a36Sopenharmony_ci else 174462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR; 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci if (ctx->sfu_emul) 174762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; 174862306a36Sopenharmony_ci else 174962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL; 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci if (ctx->nobrl) 175262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; 175362306a36Sopenharmony_ci else 175462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL; 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci if (ctx->nohandlecache) 175762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE; 175862306a36Sopenharmony_ci else 175962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE; 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci if (ctx->nostrictsync) 176262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; 176362306a36Sopenharmony_ci else 176462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC; 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci if (ctx->mand_lock) 176762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; 176862306a36Sopenharmony_ci else 176962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL; 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci if (ctx->rwpidforward) 177262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD; 177362306a36Sopenharmony_ci else 177462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD; 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci if (ctx->mode_ace) 177762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID; 177862306a36Sopenharmony_ci else 177962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID; 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci if (ctx->cifs_acl) 178262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; 178362306a36Sopenharmony_ci else 178462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL; 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci if (ctx->backupuid_specified) 178762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID; 178862306a36Sopenharmony_ci else 178962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID; 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci if (ctx->backupgid_specified) 179262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID; 179362306a36Sopenharmony_ci else 179462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID; 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_ci if (ctx->override_uid) 179762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; 179862306a36Sopenharmony_ci else 179962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID; 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci if (ctx->override_gid) 180262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; 180362306a36Sopenharmony_ci else 180462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID; 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci if (ctx->dynperm) 180762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; 180862306a36Sopenharmony_ci else 180962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM; 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_ci if (ctx->fsc) 181262306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE; 181362306a36Sopenharmony_ci else 181462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE; 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci if (ctx->multiuser) 181762306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | 181862306a36Sopenharmony_ci CIFS_MOUNT_NO_PERM); 181962306a36Sopenharmony_ci else 182062306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MULTIUSER; 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci if (ctx->strict_io) 182462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO; 182562306a36Sopenharmony_ci else 182662306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO; 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci if (ctx->direct_io) 182962306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; 183062306a36Sopenharmony_ci else 183162306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO; 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci if (ctx->mfsymlinks) 183462306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS; 183562306a36Sopenharmony_ci else 183662306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS; 183762306a36Sopenharmony_ci if (ctx->mfsymlinks) { 183862306a36Sopenharmony_ci if (ctx->sfu_emul) { 183962306a36Sopenharmony_ci /* 184062306a36Sopenharmony_ci * Our SFU ("Services for Unix" emulation does not allow 184162306a36Sopenharmony_ci * creating symlinks but does allow reading existing SFU 184262306a36Sopenharmony_ci * symlinks (it does allow both creating and reading SFU 184362306a36Sopenharmony_ci * style mknod and FIFOs though). When "mfsymlinks" and 184462306a36Sopenharmony_ci * "sfu" are both enabled at the same time, it allows 184562306a36Sopenharmony_ci * reading both types of symlinks, but will only create 184662306a36Sopenharmony_ci * them with mfsymlinks format. This allows better 184762306a36Sopenharmony_ci * Apple compatibility (probably better for Samba too) 184862306a36Sopenharmony_ci * while still recognizing old Windows style symlinks. 184962306a36Sopenharmony_ci */ 185062306a36Sopenharmony_ci cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n"); 185162306a36Sopenharmony_ci } 185262306a36Sopenharmony_ci } 185362306a36Sopenharmony_ci cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SHUTDOWN; 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci return; 185662306a36Sopenharmony_ci} 1857