diff options
author | Ronnie Sahlberg <lsahlber@redhat.com> | 2020-12-10 00:06:02 -0600 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2020-12-13 19:12:07 -0600 |
commit | 24e0a1eff9e2b9835a6e7c17039dfb6ecfd81f1f (patch) | |
tree | 56ba9dcbfc2c975fafc76582edfd18190b5737d6 | |
parent | 66e7b09c731175064de5a3682c692ec166e02499 (diff) |
cifs: switch to new mount api
See Documentation/filesystems/mount_api.rst for details on new mount API
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 4 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 5 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 54 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 5 | ||||
-rw-r--r-- | fs/cifs/connect.c | 1158 | ||||
-rw-r--r-- | fs/cifs/dfs_cache.c | 8 | ||||
-rw-r--r-- | fs/cifs/fs_context.c | 1063 | ||||
-rw-r--r-- | fs/cifs/fs_context.h | 74 | ||||
-rw-r--r-- | fs/cifs/sess.c | 2 |
10 files changed, 1096 insertions, 1281 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index cc3ada12848d..4b0b9cfe2ab1 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -275,6 +275,10 @@ static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt, convert_delimiter(devname, '/'); + /* TODO: change to call fs_context_for_mount(), fill in context directly, call fc_mount */ + + /* See afs_mntpt_do_automount in fs/afs/mntpt.c for an example */ + /* strip first '\' from fullpath */ mountdata = cifs_compose_mount_options(cifs_sb->mountdata, fullpath + 1, NULL, NULL); diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 9daa256f69d4..51d53e4bdf6b 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -661,6 +661,11 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) unsigned char *tiblob = NULL; /* target info blob */ __le64 rsp_timestamp; + if (nls_cp == NULL) { + cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__); + return -EINVAL; + } + if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) { if (!ses->domainName) { if (ses->domainAuto) { diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9fb85fcff6ae..907c82428c42 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -682,13 +682,6 @@ static int cifs_show_stats(struct seq_file *s, struct dentry *root) } #endif -static int cifs_remount(struct super_block *sb, int *flags, char *data) -{ - sync_filesystem(sb); - *flags |= SB_NODIRATIME; - return 0; -} - static int cifs_drop_inode(struct inode *inode) { struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); @@ -710,7 +703,6 @@ static const struct super_operations cifs_super_ops = { as opens */ .show_options = cifs_show_options, .umount_begin = cifs_umount_begin, - .remount_fs = cifs_remount, #ifdef CONFIG_CIFS_STATS2 .show_stats = cifs_show_stats, #endif @@ -778,9 +770,9 @@ static int cifs_set_super(struct super_block *sb, void *data) return set_anon_super(sb, NULL); } -static struct dentry * +struct dentry * cifs_smb3_do_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data, bool is_smb3) + int flags, struct smb3_fs_context *old_ctx) { int rc; struct super_block *sb; @@ -794,13 +786,24 @@ cifs_smb3_do_mount(struct file_system_type *fs_type, * If CIFS_DEBUG && cifs_FYI */ if (cifsFYI) - cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags); + cifs_dbg(FYI, "Devname: %s flags: %d\n", old_ctx->UNC, flags); else - cifs_info("Attempting to mount %s\n", dev_name); + cifs_info("Attempting to mount %s\n", old_ctx->UNC); + + ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); + rc = smb3_fs_context_dup(ctx, old_ctx); + if (rc) { + root = ERR_PTR(rc); + goto out; + } - ctx = cifs_get_volume_info((char *)data, dev_name, is_smb3); - if (IS_ERR(ctx)) - return ERR_CAST(ctx); + rc = cifs_setup_volume_info(ctx); + if (rc) { + root = ERR_PTR(rc); + goto out; + } cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); if (cifs_sb == NULL) { @@ -808,7 +811,7 @@ cifs_smb3_do_mount(struct file_system_type *fs_type, goto out_nls; } - cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); + cifs_sb->mountdata = kstrndup(ctx->mount_options, PAGE_SIZE, GFP_KERNEL); if (cifs_sb->mountdata == NULL) { root = ERR_PTR(-ENOMEM); goto out_free; @@ -878,19 +881,6 @@ out_nls: goto out; } -static struct dentry * -smb3_do_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) -{ - return cifs_smb3_do_mount(fs_type, flags, dev_name, data, true); -} - -static struct dentry * -cifs_do_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) -{ - return cifs_smb3_do_mount(fs_type, flags, dev_name, data, false); -} static ssize_t cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter) @@ -1027,7 +1017,8 @@ cifs_setlease(struct file *file, long arg, struct file_lock **lease, void **priv struct file_system_type cifs_fs_type = { .owner = THIS_MODULE, .name = "cifs", - .mount = cifs_do_mount, + .init_fs_context = smb3_init_fs_context, + .parameters = smb3_fs_parameters, .kill_sb = cifs_kill_sb, .fs_flags = FS_RENAME_DOES_D_MOVE, }; @@ -1036,7 +1027,8 @@ MODULE_ALIAS_FS("cifs"); static struct file_system_type smb3_fs_type = { .owner = THIS_MODULE, .name = "smb3", - .mount = smb3_do_mount, + .init_fs_context = smb3_init_fs_context, + .parameters = smb3_fs_parameters, .kill_sb = cifs_kill_sb, .fs_flags = FS_RENAME_DOES_D_MOVE, }; diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 905d03863721..d6976c28970d 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -152,6 +152,10 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern void cifs_setsize(struct inode *inode, loff_t offset); extern int cifs_truncate_page(struct address_space *mapping, loff_t from); +struct smb3_fs_context; +extern struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type, + int flags, struct smb3_fs_context *ctx); + #ifdef CONFIG_CIFS_NFSD_EXPORT extern const struct export_operations cifs_export_ops; #endif /* CONFIG_CIFS_NFSD_EXPORT */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0ef3deeb085f..8dde386d4893 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -239,8 +239,6 @@ extern int cifs_setup_cifs_sb(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb); extern int cifs_match_super(struct super_block *, void *); extern void cifs_cleanup_volume_info(struct smb3_fs_context *ctx); -extern struct smb3_fs_context *cifs_get_volume_info(char *mount_data, - const char *devname, bool is_smb3); extern int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx); extern void cifs_umount(struct cifs_sb_info *); extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon); @@ -554,8 +552,7 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24); extern int -cifs_setup_volume_info(struct smb3_fs_context *ctx, char *mount_data, - const char *devname, bool is_smb3); +cifs_setup_volume_info(struct smb3_fs_context *ctx); extern void cifs_cleanup_volume_info_contents(struct smb3_fs_context *ctx); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8ae45367109c..1c463ca16226 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -73,156 +73,6 @@ extern bool disable_legacy_dialects; /* Drop the connection to not overload the server */ #define NUM_STATUS_IO_TIMEOUT 5 -static const match_table_t cifs_mount_option_tokens = { - - { Opt_user_xattr, "user_xattr" }, - { Opt_nouser_xattr, "nouser_xattr" }, - { Opt_forceuid, "forceuid" }, - { Opt_noforceuid, "noforceuid" }, - { Opt_forcegid, "forcegid" }, - { Opt_noforcegid, "noforcegid" }, - { Opt_noblocksend, "noblocksend" }, - { Opt_noautotune, "noautotune" }, - { Opt_nolease, "nolease" }, - { Opt_hard, "hard" }, - { Opt_soft, "soft" }, - { Opt_perm, "perm" }, - { Opt_noperm, "noperm" }, - { Opt_nodelete, "nodelete" }, - { Opt_mapchars, "mapchars" }, /* SFU style */ - { Opt_nomapchars, "nomapchars" }, - { Opt_mapposix, "mapposix" }, /* SFM style */ - { Opt_nomapposix, "nomapposix" }, - { Opt_sfu, "sfu" }, - { Opt_nosfu, "nosfu" }, - { Opt_nodfs, "nodfs" }, - { Opt_posixpaths, "posixpaths" }, - { Opt_noposixpaths, "noposixpaths" }, - { Opt_nounix, "nounix" }, - { Opt_nounix, "nolinux" }, - { Opt_nounix, "noposix" }, - { Opt_unix, "unix" }, - { Opt_unix, "linux" }, - { Opt_unix, "posix" }, - { Opt_nocase, "nocase" }, - { Opt_nocase, "ignorecase" }, - { Opt_brl, "brl" }, - { Opt_nobrl, "nobrl" }, - { Opt_handlecache, "handlecache" }, - { Opt_nohandlecache, "nohandlecache" }, - { Opt_nobrl, "nolock" }, - { Opt_forcemandatorylock, "forcemandatorylock" }, - { Opt_forcemandatorylock, "forcemand" }, - { Opt_setuids, "setuids" }, - { Opt_nosetuids, "nosetuids" }, - { Opt_setuidfromacl, "idsfromsid" }, - { Opt_dynperm, "dynperm" }, - { Opt_nodynperm, "nodynperm" }, - { Opt_nohard, "nohard" }, - { Opt_nosoft, "nosoft" }, - { Opt_nointr, "nointr" }, - { Opt_intr, "intr" }, - { Opt_nostrictsync, "nostrictsync" }, - { Opt_strictsync, "strictsync" }, - { Opt_serverino, "serverino" }, - { Opt_noserverino, "noserverino" }, - { Opt_rwpidforward, "rwpidforward" }, - { Opt_modesid, "modefromsid" }, - { Opt_cifsacl, "cifsacl" }, - { Opt_nocifsacl, "nocifsacl" }, - { Opt_acl, "acl" }, - { Opt_noacl, "noacl" }, - { Opt_locallease, "locallease" }, - { Opt_sign, "sign" }, - { Opt_ignore_signature, "signloosely" }, - { Opt_seal, "seal" }, - { Opt_noac, "noac" }, - { Opt_fsc, "fsc" }, - { Opt_mfsymlinks, "mfsymlinks" }, - { Opt_multiuser, "multiuser" }, - { Opt_sloppy, "sloppy" }, - { Opt_nosharesock, "nosharesock" }, - { Opt_persistent, "persistenthandles"}, - { Opt_nopersistent, "nopersistenthandles"}, - { Opt_resilient, "resilienthandles"}, - { Opt_noresilient, "noresilienthandles"}, - { Opt_domainauto, "domainauto"}, - { Opt_rdma, "rdma"}, - { Opt_multichannel, "multichannel" }, - { Opt_nomultichannel, "nomultichannel" }, - - { Opt_backupuid, "backupuid=%s" }, - { Opt_backupgid, "backupgid=%s" }, - { Opt_uid, "uid=%s" }, - { Opt_cruid, "cruid=%s" }, - { Opt_gid, "gid=%s" }, - { Opt_file_mode, "file_mode=%s" }, - { Opt_dirmode, "dirmode=%s" }, - { Opt_dirmode, "dir_mode=%s" }, - { Opt_port, "port=%s" }, - { Opt_min_enc_offload, "esize=%s" }, - { Opt_blocksize, "bsize=%s" }, - { Opt_rsize, "rsize=%s" }, - { Opt_wsize, "wsize=%s" }, - { Opt_actimeo, "actimeo=%s" }, - { Opt_handletimeout, "handletimeout=%s" }, - { Opt_echo_interval, "echo_interval=%s" }, - { Opt_max_credits, "max_credits=%s" }, - { Opt_snapshot, "snapshot=%s" }, - { Opt_max_channels, "max_channels=%s" }, - { Opt_compress, "compress=%s" }, - - { Opt_blank_user, "user=" }, - { Opt_blank_user, "username=" }, - { Opt_user, "user=%s" }, - { Opt_user, "username=%s" }, - { Opt_blank_pass, "pass=" }, - { Opt_blank_pass, "password=" }, - { Opt_pass, "pass=%s" }, - { Opt_pass, "password=%s" }, - { Opt_blank_ip, "ip=" }, - { Opt_blank_ip, "addr=" }, - { Opt_ip, "ip=%s" }, - { Opt_ip, "addr=%s" }, - { Opt_ignore, "unc=%s" }, - { Opt_ignore, "target=%s" }, - { Opt_ignore, "path=%s" }, - { Opt_domain, "dom=%s" }, - { Opt_domain, "domain=%s" }, - { Opt_domain, "workgroup=%s" }, - { Opt_srcaddr, "srcaddr=%s" }, - { Opt_ignore, "prefixpath=%s" }, - { Opt_iocharset, "iocharset=%s" }, - { Opt_netbiosname, "netbiosname=%s" }, - { Opt_servern, "servern=%s" }, - { Opt_ver, "ver=%s" }, - { Opt_vers, "vers=%s" }, - { Opt_sec, "sec=%s" }, - { Opt_cache, "cache=%s" }, - - { Opt_ignore, "cred" }, - { Opt_ignore, "credentials" }, - { Opt_ignore, "cred=%s" }, - { Opt_ignore, "credentials=%s" }, - { Opt_ignore, "guest" }, - { Opt_ignore, "rw" }, - { Opt_ignore, "ro" }, - { Opt_ignore, "suid" }, - { Opt_ignore, "nosuid" }, - { Opt_ignore, "exec" }, - { Opt_ignore, "noexec" }, - { Opt_ignore, "nodev" }, - { Opt_ignore, "noauto" }, - { Opt_ignore, "dev" }, - { Opt_ignore, "mand" }, - { Opt_ignore, "nomand" }, - { Opt_ignore, "relatime" }, - { Opt_ignore, "_netdev" }, - { Opt_rootfs, "rootfs" }, - - { Opt_err, NULL } -}; - static int ip_connect(struct TCP_Server_Info *server); static int generic_ip_connect(struct TCP_Server_Info *server); static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); @@ -1208,960 +1058,6 @@ extract_hostname(const char *unc) return dst; } -static int get_option_ul(substring_t args[], unsigned long *option) -{ - int rc; - char *string; - - string = match_strdup(args); - if (string == NULL) - return -ENOMEM; - rc = kstrtoul(string, 0, option); - kfree(string); - - return rc; -} - -static int get_option_uid(substring_t args[], kuid_t *result) -{ - unsigned long value; - kuid_t uid; - int rc; - - rc = get_option_ul(args, &value); - if (rc) - return rc; - - uid = make_kuid(current_user_ns(), value); - if (!uid_valid(uid)) - return -EINVAL; - - *result = uid; - return 0; -} - -static int get_option_gid(substring_t args[], kgid_t *result) -{ - unsigned long value; - kgid_t gid; - int rc; - - rc = get_option_ul(args, &value); - if (rc) - return rc; - - gid = make_kgid(current_user_ns(), value); - if (!gid_valid(gid)) - return -EINVAL; - - *result = gid; - return 0; -} - -static int -cifs_parse_mount_options(const char *mountdata, const char *devname, - struct smb3_fs_context *ctx, bool is_smb3) -{ - char *data, *end; - char *mountdata_copy = NULL, *options; - unsigned int temp_len, i, j; - char separator[2]; - short int override_uid = -1; - short int override_gid = -1; - bool uid_specified = false; - bool gid_specified = false; - bool sloppy = false; - char *invalid = NULL; - char *nodename = utsname()->nodename; - char *string = NULL; - char *tmp_end, *value; - char delim; - bool got_ip = false; - bool got_version = false; - unsigned short port = 0; - struct sockaddr *dstaddr = (struct sockaddr *)&ctx->dstaddr; - - separator[0] = ','; - separator[1] = 0; - delim = separator[0]; - - /* ensure we always start with zeroed-out ctx */ - memset(ctx, 0, sizeof(*ctx)); - - /* - * does not have to be perfect mapping since field is - * informational, only used for servers that do not support - * port 445 and it can be overridden at mount time - */ - memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN); - for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++) - ctx->source_rfc1001_name[i] = toupper(nodename[i]); - - ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0; - /* null target name indicates to use *SMBSERVR default called name - if we end up sending RFC1001 session initialize */ - ctx->target_rfc1001_name[0] = 0; - ctx->cred_uid = current_uid(); - ctx->linux_uid = current_uid(); - ctx->linux_gid = current_gid(); - ctx->bsize = 1024 * 1024; /* can improve cp performance significantly */ - /* - * default to SFM style remapping of seven reserved characters - * unless user overrides it or we negotiate CIFS POSIX where - * it is unnecessary. Can not simultaneously use more than one mapping - * since then readdir could list files that open could not open - */ - ctx->remap = true; - - /* default to only allowing write access to owner of the mount */ - ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; - - /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */ - /* default is always to request posix paths. */ - ctx->posix_paths = 1; - /* default to using server inode numbers where available */ - ctx->server_ino = 1; - - /* default is to use strict cifs caching semantics */ - ctx->strict_io = true; - - ctx->actimeo = CIFS_DEF_ACTIMEO; - - /* Most clients set timeout to 0, allows server to use its default */ - ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */ - - /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */ - ctx->ops = &smb30_operations; - ctx->vals = &smbdefault_values; - - ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT; - - /* default to no multichannel (single server connection) */ - ctx->multichannel = false; - ctx->max_channels = 1; - - if (!mountdata) - goto cifs_parse_mount_err; - - mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL); - if (!mountdata_copy) - goto cifs_parse_mount_err; - - options = mountdata_copy; - end = options + strlen(options); - - if (strncmp(options, "sep=", 4) == 0) { - if (options[4] != 0) { - separator[0] = options[4]; - options += 5; - } else { - cifs_dbg(FYI, "Null separator not allowed\n"); - } - } - ctx->backupuid_specified = false; /* no backup intent for a user */ - ctx->backupgid_specified = false; /* no backup intent for a group */ - - switch (smb3_parse_devname(devname, ctx)) { - case 0: - break; - case -ENOMEM: - cifs_dbg(VFS, "Unable to allocate memory for devname\n"); - goto cifs_parse_mount_err; - case -EINVAL: - cifs_dbg(VFS, "Malformed UNC in devname\n"); - goto cifs_parse_mount_err; - default: - cifs_dbg(VFS, "Unknown error parsing devname\n"); - goto cifs_parse_mount_err; - } - - while ((data = strsep(&options, separator)) != NULL) { - substring_t args[MAX_OPT_ARGS]; - unsigned long option; - int token; - - if (!*data) - continue; - - token = match_token(data, cifs_mount_option_tokens, args); - - switch (token) { - - /* Ingnore the following */ - case Opt_ignore: - break; - - /* Boolean values */ - case Opt_user_xattr: - ctx->no_xattr = 0; - break; - case Opt_nouser_xattr: - ctx->no_xattr = 1; - break; - case Opt_forceuid: - override_uid = 1; - break; - case Opt_noforceuid: - override_uid = 0; - break; - case Opt_forcegid: - override_gid = 1; - break; - case Opt_noforcegid: - override_gid = 0; - break; - case Opt_noblocksend: - ctx->noblocksnd = 1; - break; - case Opt_noautotune: - ctx->noautotune = 1; - break; - case Opt_nolease: - ctx->no_lease = 1; - break; - case Opt_hard: - ctx->retry = 1; - break; - case Opt_soft: - ctx->retry = 0; - break; - case Opt_perm: - ctx->noperm = 0; - break; - case Opt_noperm: - ctx->noperm = 1; - break; - case Opt_nodelete: - ctx->nodelete = 1; - break; - case Opt_mapchars: - ctx->sfu_remap = true; - ctx->remap = false; /* disable SFM mapping */ - break; - case Opt_nomapchars: - ctx->sfu_remap = false; - break; - case Opt_mapposix: - ctx->remap = true; - ctx->sfu_remap = false; /* disable SFU mapping */ - break; - case Opt_nomapposix: - ctx->remap = false; - break; - case Opt_sfu: - ctx->sfu_emul = 1; - break; - case Opt_nosfu: - ctx->sfu_emul = 0; - break; - case Opt_nodfs: - ctx->nodfs = 1; - break; - case Opt_rootfs: -#ifdef CONFIG_CIFS_ROOT - ctx->rootfs = true; -#endif - break; - case Opt_posixpaths: - ctx->posix_paths = 1; - break; - case Opt_noposixpaths: - ctx->posix_paths = 0; - break; - case Opt_nounix: - if (ctx->linux_ext) - cifs_dbg(VFS, - "conflicting unix mount options\n"); - ctx->no_linux_ext = 1; - break; - case Opt_unix: - if (ctx->no_linux_ext) - cifs_dbg(VFS, - "conflicting unix mount options\n"); - ctx->linux_ext = 1; - break; - case Opt_nocase: - ctx->nocase = 1; - break; - case Opt_brl: - ctx->nobrl = 0; - break; - case Opt_nobrl: - ctx->nobrl = 1; - /* - * turn off mandatory locking in mode - * if remote locking is turned off since the - * local vfs will do advisory - */ - if (ctx->file_mode == - (S_IALLUGO & ~(S_ISUID | S_IXGRP))) - ctx->file_mode = S_IALLUGO; - break; - case Opt_nohandlecache: - ctx->nohandlecache = 1; - break; - case Opt_handlecache: - ctx->nohandlecache = 0; - break; - case Opt_forcemandatorylock: - ctx->mand_lock = 1; - break; - case Opt_setuids: - ctx->setuids = 1; - break; - case Opt_nosetuids: - ctx->setuids = 0; - break; - case Opt_setuidfromacl: - ctx->setuidfromacl = 1; - break; - case Opt_dynperm: - ctx->dynperm = true; - break; - case Opt_nodynperm: - ctx->dynperm = false; - break; - case Opt_nohard: - ctx->retry = 0; - break; - case Opt_nosoft: - ctx->retry = 1; - break; - case Opt_nointr: - ctx->intr = 0; - break; - case Opt_intr: - ctx->intr = 1; - break; - case Opt_nostrictsync: - ctx->nostrictsync = 1; - break; - case Opt_strictsync: - ctx->nostrictsync = 0; - break; - case Opt_serverino: - ctx->server_ino = 1; - break; - case Opt_noserverino: - ctx->server_ino = 0; - break; - case Opt_rwpidforward: - ctx->rwpidforward = 1; - break; - case Opt_modesid: - ctx->mode_ace = 1; - break; - case Opt_cifsacl: - ctx->cifs_acl = 1; - break; - case Opt_nocifsacl: - ctx->cifs_acl = 0; - break; - case Opt_acl: - ctx->no_psx_acl = 0; - break; - case Opt_noacl: - ctx->no_psx_acl = 1; - break; - case Opt_locallease: - ctx->local_lease = 1; - break; - case Opt_sign: - ctx->sign = true; - break; - case Opt_ignore_signature: - ctx->sign = true; - ctx->ignore_signature = true; - break; - case Opt_seal: - /* we do not do the following in secFlags because seal - * is a per tree connection (mount) not a per socket - * or per-smb connection option in the protocol - * ctx->secFlg |= CIFSSEC_MUST_SEAL; - */ - ctx->seal = 1; - break; - case Opt_noac: - pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n"); - break; - case Opt_fsc: -#ifndef CONFIG_CIFS_FSCACHE - cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n"); - goto cifs_parse_mount_err; -#endif - ctx->fsc = true; - break; - case Opt_mfsymlinks: - ctx->mfsymlinks = true; - break; - case Opt_multiuser: - ctx->multiuser = true; - break; - case Opt_sloppy: - sloppy = true; - break; - case Opt_nosharesock: - ctx->nosharesock = true; - break; - case Opt_nopersistent: - ctx->nopersistent = true; - if (ctx->persistent) { - cifs_dbg(VFS, - "persistenthandles mount options conflict\n"); - goto cifs_parse_mount_err; - } - break; - case Opt_persistent: - ctx->persistent = true; - if ((ctx->nopersistent) || (ctx->resilient)) { - cifs_dbg(VFS, - "persistenthandles mount options conflict\n"); - goto cifs_parse_mount_err; - } - break; - case Opt_resilient: - ctx->resilient = true; - if (ctx->persistent) { - cifs_dbg(VFS, - "persistenthandles mount options conflict\n"); - goto cifs_parse_mount_err; - } - break; - case Opt_noresilient: - ctx->resilient = false; /* already the default */ - break; - case Opt_domainauto: - ctx->domainauto = true; - break; - case Opt_rdma: - ctx->rdma = true; - break; - case Opt_multichannel: - ctx->multichannel = true; - /* if number of channels not specified, default to 2 */ - if (ctx->max_channels < 2) - ctx->max_channels = 2; - break; - case Opt_nomultichannel: - ctx->multichannel = false; - ctx->max_channels = 1; - break; - case Opt_compress: - ctx->compression = UNKNOWN_TYPE; - cifs_dbg(VFS, - "SMB3 compression support is experimental\n"); - break; - - /* Numeric Values */ - case Opt_backupuid: - if (get_option_uid(args, &ctx->backupuid)) { - cifs_dbg(VFS, "%s: Invalid backupuid value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->backupuid_specified = true; - break; - case Opt_backupgid: - if (get_option_gid(args, &ctx->backupgid)) { - cifs_dbg(VFS, "%s: Invalid backupgid value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->backupgid_specified = true; - break; - case Opt_uid: - if (get_option_uid(args, &ctx->linux_uid)) { - cifs_dbg(VFS, "%s: Invalid uid value\n", - __func__); - goto cifs_parse_mount_err; - } - uid_specified = true; - break; - case Opt_cruid: - if (get_option_uid(args, &ctx->cred_uid)) { - cifs_dbg(VFS, "%s: Invalid cruid value\n", - __func__); - goto cifs_parse_mount_err; - } - break; - case Opt_gid: - if (get_option_gid(args, &ctx->linux_gid)) { - cifs_dbg(VFS, "%s: Invalid gid value\n", - __func__); - goto cifs_parse_mount_err; - } - gid_specified = true; - break; - case Opt_file_mode: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "%s: Invalid file_mode value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->file_mode = option; - break; - case Opt_dirmode: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "%s: Invalid dir_mode value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->dir_mode = option; - break; - case Opt_port: - if (get_option_ul(args, &option) || - option > USHRT_MAX) { - cifs_dbg(VFS, "%s: Invalid port value\n", - __func__); - goto cifs_parse_mount_err; - } - port = (unsigned short)option; - break; - case Opt_min_enc_offload: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n"); - goto cifs_parse_mount_err; - } - ctx->min_offload = option; - break; - case Opt_blocksize: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "%s: Invalid blocksize value\n", - __func__); - goto cifs_parse_mount_err; - } - /* - * inode blocksize realistically should never need to be - * less than 16K or greater than 16M and default is 1MB. - * Note that small inode block sizes (e.g. 64K) can lead - * to very poor performance of common tools like cp and scp - */ - if ((option < CIFS_MAX_MSGSIZE) || - (option > (4 * SMB3_DEFAULT_IOSIZE))) { - cifs_dbg(VFS, "%s: Invalid blocksize\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->bsize = option; - break; - case Opt_rsize: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "%s: Invalid rsize value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->rsize = option; - break; - case Opt_wsize: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "%s: Invalid wsize value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->wsize = option; - break; - case Opt_actimeo: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "%s: Invalid actimeo value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->actimeo = HZ * option; - if (ctx->actimeo > CIFS_MAX_ACTIMEO) { - cifs_dbg(VFS, "attribute cache timeout too large\n"); - goto cifs_parse_mount_err; - } - break; - case Opt_handletimeout: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "%s: Invalid handletimeout value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->handle_timeout = option; - if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) { - cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n"); - goto cifs_parse_mount_err; - } - break; - case Opt_echo_interval: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "%s: Invalid echo interval value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->echo_interval = option; - break; - case Opt_snapshot: - if (get_option_ul(args, &option)) { - cifs_dbg(VFS, "%s: Invalid snapshot time\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->snapshot_time = option; - break; - case Opt_max_credits: - if (get_option_ul(args, &option) || (option < 20) || - (option > 60000)) { - cifs_dbg(VFS, "%s: Invalid max_credits value\n", - __func__); - goto cifs_parse_mount_err; - } - ctx->max_credits = option; - break; - case Opt_max_channels: - if (get_option_ul(args, &option) || option < 1 || - option > CIFS_MAX_CHANNELS) { - cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n", - __func__, CIFS_MAX_CHANNELS); - goto cifs_parse_mount_err; - } - ctx->max_channels = option; - break; - - /* String Arguments */ - - case Opt_blank_user: - /* null user, ie. anonymous authentication */ - ctx->nullauth = 1; - ctx->username = NULL; - break; - case Opt_user: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, CIFS_MAX_USERNAME_LEN) > - CIFS_MAX_USERNAME_LEN) { - pr_warn("username too long\n"); - goto cifs_parse_mount_err; - } - - kfree(ctx->username); - ctx->username = kstrdup(string, GFP_KERNEL); - if (!ctx->username) - goto cifs_parse_mount_err; - break; - case Opt_blank_pass: - /* passwords have to be handled differently - * to allow the character used for deliminator - * to be passed within them - */ - - /* - * Check if this is a case where the password - * starts with a delimiter - */ - tmp_end = strchr(data, '='); - tmp_end++; - if (!(tmp_end < end && tmp_end[1] == delim)) { - /* No it is not. Set the password to NULL */ - kfree_sensitive(ctx->password); - ctx->password = NULL; - break; - } - fallthrough; /* to Opt_pass below */ - case Opt_pass: - /* Obtain the value string */ - value = strchr(data, '='); - value++; - - /* Set tmp_end to end of the string */ - tmp_end = (char *) value + strlen(value); - - /* Check if following character is the deliminator - * If yes, we have encountered a double deliminator - * reset the NULL character to the deliminator - */ - if (tmp_end < end && tmp_end[1] == delim) { - tmp_end[0] = delim; - - /* Keep iterating until we get to a single - * deliminator OR the end - */ - while ((tmp_end = strchr(tmp_end, delim)) - != NULL && (tmp_end[1] == delim)) { - tmp_end = (char *) &tmp_end[2]; - } - - /* Reset var options to point to next element */ - if (tmp_end) { - tmp_end[0] = '\0'; - options = (char *) &tmp_end[1]; - } else - /* Reached the end of the mount option - * string */ - options = end; - } - - kfree_sensitive(ctx->password); - /* Now build new password string */ - temp_len = strlen(value); - ctx->password = kzalloc(temp_len+1, GFP_KERNEL); - if (ctx->password == NULL) { - pr_warn("no memory for password\n"); - goto cifs_parse_mount_err; - } - - for (i = 0, j = 0; i < temp_len; i++, j++) { - ctx->password[j] = value[i]; - if ((value[i] == delim) && - value[i+1] == delim) - /* skip the second deliminator */ - i++; - } - ctx->password[j] = '\0'; - break; - case Opt_blank_ip: - /* FIXME: should this be an error instead? */ - got_ip = false; - break; - case Opt_ip: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (!cifs_convert_address(dstaddr, string, - strlen(string))) { - pr_err("bad ip= option (%s)\n", string); - goto cifs_parse_mount_err; - } - got_ip = true; - break; - case Opt_domain: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN) - == CIFS_MAX_DOMAINNAME_LEN) { - pr_warn("domain name too long\n"); - goto cifs_parse_mount_err; - } - - kfree(ctx->domainname); - ctx->domainname = kstrdup(string, GFP_KERNEL); - if (!ctx->domainname) { - pr_warn("no memory for domainname\n"); - goto cifs_parse_mount_err; - } - cifs_dbg(FYI, "Domain name set\n"); - break; - case Opt_srcaddr: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (!cifs_convert_address( - (struct |