| /* SPDX-License-Identifier: GPL-2.0-or-later */ | |
| /* | |
| * Copyright (C) 2020, Microsoft Corporation. | |
| * | |
| * Author(s): Steve French <stfrench@microsoft.com> | |
| * David Howells <dhowells@redhat.com> | |
| */ | |
| #ifndef _FS_CONTEXT_H | |
| #define _FS_CONTEXT_H | |
| #include "cifsglob.h" | |
| #include <linux/parser.h> | |
| #include <linux/fs_parser.h> | |
| /* Log errors in fs_context (new mount api) but also in dmesg (old style) */ | |
| #define cifs_errorf(fc, fmt, ...) \ | |
| do { \ | |
| errorf(fc, fmt, ## __VA_ARGS__); \ | |
| cifs_dbg(VFS, fmt, ## __VA_ARGS__); \ | |
| } while (0) | |
| static inline size_t cifs_io_align(struct fs_context *fc, | |
| const char *name, size_t size) | |
| { | |
| if (!size || !IS_ALIGNED(size, PAGE_SIZE)) { | |
| cifs_errorf(fc, "unaligned %s, making it a multiple of %lu bytes\n", | |
| name, PAGE_SIZE); | |
| size = umax(round_down(size, PAGE_SIZE), PAGE_SIZE); | |
| } | |
| return size; | |
| } | |
| #define CIFS_ALIGN_WSIZE(_fc, _size) cifs_io_align(_fc, "wsize", _size) | |
| #define CIFS_ALIGN_RSIZE(_fc, _size) cifs_io_align(_fc, "rsize", _size) | |
| #define CIFS_ALIGN_BSIZE(_fc, _size) cifs_io_align(_fc, "bsize", _size) | |
| enum smb_version { | |
| Smb_1 = 1, | |
| Smb_20, | |
| Smb_21, | |
| Smb_30, | |
| Smb_302, | |
| Smb_311, | |
| Smb_3any, | |
| Smb_default, | |
| Smb_version_err | |
| }; | |
| enum { | |
| Opt_cache_loose, | |
| Opt_cache_strict, | |
| Opt_cache_none, | |
| Opt_cache_ro, | |
| Opt_cache_rw, | |
| Opt_cache_err | |
| }; | |
| enum cifs_reparse_parm { | |
| Opt_reparse_default, | |
| Opt_reparse_none, | |
| Opt_reparse_nfs, | |
| Opt_reparse_wsl, | |
| Opt_reparse_err | |
| }; | |
| enum cifs_symlink_parm { | |
| Opt_symlink_default, | |
| Opt_symlink_none, | |
| Opt_symlink_native, | |
| Opt_symlink_unix, | |
| Opt_symlink_mfsymlinks, | |
| Opt_symlink_sfu, | |
| Opt_symlink_nfs, | |
| Opt_symlink_wsl, | |
| Opt_symlink_err | |
| }; | |
| enum cifs_sec_param { | |
| Opt_sec_krb5, | |
| Opt_sec_krb5i, | |
| Opt_sec_krb5p, | |
| Opt_sec_ntlmsspi, | |
| Opt_sec_ntlmssp, | |
| Opt_sec_ntlmv2, | |
| Opt_sec_ntlmv2i, | |
| Opt_sec_none, | |
| Opt_sec_err | |
| }; | |
| enum cifs_upcall_target_param { | |
| Opt_upcall_target_mount, | |
| Opt_upcall_target_application, | |
| Opt_upcall_target_err | |
| }; | |
| enum cifs_param { | |
| /* Mount options that take no arguments */ | |
| Opt_user_xattr, | |
| Opt_forceuid, | |
| Opt_forcegid, | |
| Opt_noblocksend, | |
| Opt_noautotune, | |
| Opt_lease, | |
| Opt_nosparse, | |
| Opt_hard, | |
| Opt_soft, | |
| Opt_perm, | |
| Opt_nodelete, | |
| Opt_mapposix, | |
| Opt_mapchars, | |
| Opt_nomapchars, | |
| Opt_sfu, | |
| Opt_nodfs, | |
| Opt_posixpaths, | |
| Opt_unix, | |
| Opt_nocase, | |
| Opt_brl, | |
| Opt_handlecache, | |
| Opt_forcemandatorylock, | |
| Opt_setuidfromacl, | |
| Opt_setuids, | |
| Opt_dynperm, | |
| Opt_intr, | |
| Opt_strictsync, | |
| Opt_serverino, | |
| Opt_rwpidforward, | |
| Opt_cifsacl, | |
| Opt_acl, | |
| Opt_locallease, | |
| Opt_sign, | |
| Opt_ignore_signature, | |
| Opt_seal, | |
| Opt_noac, | |
| Opt_fsc, | |
| Opt_mfsymlinks, | |
| Opt_multiuser, | |
| Opt_sloppy, | |
| Opt_nosharesock, | |
| Opt_persistent, | |
| Opt_resilient, | |
| Opt_tcp_nodelay, | |
| Opt_domainauto, | |
| Opt_rdma, | |
| Opt_modesid, | |
| Opt_rootfs, | |
| Opt_multichannel, | |
| Opt_compress, | |
| Opt_witness, | |
| Opt_is_upcall_target_mount, | |
| Opt_is_upcall_target_application, | |
| Opt_unicode, | |
| /* Mount options which take numeric value */ | |
| Opt_backupuid, | |
| Opt_backupgid, | |
| Opt_uid, | |
| Opt_cruid, | |
| Opt_gid, | |
| Opt_port, | |
| Opt_file_mode, | |
| Opt_dirmode, | |
| Opt_min_enc_offload, | |
| Opt_retrans, | |
| Opt_blocksize, | |
| Opt_rasize, | |
| Opt_rsize, | |
| Opt_wsize, | |
| Opt_actimeo, | |
| Opt_acdirmax, | |
| Opt_acregmax, | |
| Opt_closetimeo, | |
| Opt_echo_interval, | |
| Opt_max_credits, | |
| Opt_max_cached_dirs, | |
| Opt_snapshot, | |
| Opt_max_channels, | |
| Opt_handletimeout, | |
| /* Mount options which take string value */ | |
| Opt_source, | |
| Opt_user, | |
| Opt_pass, | |
| Opt_pass2, | |
| Opt_ip, | |
| Opt_domain, | |
| Opt_srcaddr, | |
| Opt_iocharset, | |
| Opt_netbiosname, | |
| Opt_servern, | |
| Opt_nbsessinit, | |
| Opt_ver, | |
| Opt_vers, | |
| Opt_sec, | |
| Opt_cache, | |
| Opt_reparse, | |
| Opt_upcalltarget, | |
| Opt_nativesocket, | |
| Opt_symlink, | |
| Opt_symlinkroot, | |
| /* Mount options to be ignored */ | |
| Opt_ignore, | |
| Opt_err | |
| }; | |
| struct smb3_fs_context { | |
| bool forceuid_specified; | |
| bool forcegid_specified; | |
| bool uid_specified; | |
| bool cruid_specified; | |
| bool gid_specified; | |
| bool sloppy; | |
| bool got_ip; | |
| bool got_version; | |
| bool got_rsize; | |
| bool got_wsize; | |
| bool got_bsize; | |
| unsigned short port; | |
| char *username; | |
| char *password; | |
| char *password2; | |
| char *domainname; | |
| char *source; | |
| char *server_hostname; | |
| char *UNC; | |
| char *nodename; | |
| char workstation_name[CIFS_MAX_WORKSTATION_LEN]; | |
| char *iocharset; /* local code page for mapping to and from Unicode */ | |
| char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */ | |
| char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */ | |
| int rfc1001_sessinit; | |
| kuid_t cred_uid; | |
| kuid_t linux_uid; | |
| kgid_t linux_gid; | |
| kuid_t backupuid; | |
| kgid_t backupgid; | |
| umode_t file_mode; | |
| umode_t dir_mode; | |
| enum securityEnum sectype; /* sectype requested via mnt opts */ | |
| enum upcall_target_enum upcall_target; /* where to upcall for mount */ | |
| bool sign; /* was signing requested via mnt opts? */ | |
| bool ignore_signature:1; | |
| bool retry:1; | |
| bool intr:1; | |
| bool setuids:1; | |
| bool setuidfromacl:1; | |
| bool override_uid:1; | |
| bool override_gid:1; | |
| bool dynperm:1; | |
| bool noperm:1; | |
| bool nodelete:1; | |
| bool mode_ace:1; | |
| bool no_psx_acl:1; /* set if posix acl support should be disabled */ | |
| bool cifs_acl:1; | |
| bool backupuid_specified; /* mount option backupuid is specified */ | |
| bool backupgid_specified; /* mount option backupgid is specified */ | |
| bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ | |
| bool server_ino:1; /* use inode numbers from server ie UniqueId */ | |
| bool direct_io:1; | |
| bool strict_io:1; /* strict cache behavior */ | |
| bool cache_ro:1; | |
| bool cache_rw:1; | |
| bool remap:1; /* set to remap seven reserved chars in filenames */ | |
| bool sfu_remap:1; /* remap seven reserved chars ala SFU */ | |
| bool posix_paths:1; /* unset to not ask for posix pathnames. */ | |
| bool no_linux_ext:1; | |
| bool linux_ext:1; | |
| bool sfu_emul:1; | |
| bool nullauth:1; /* attempt to authenticate with null user */ | |
| bool nocase:1; /* request case insensitive filenames */ | |
| bool nobrl:1; /* disable sending byte range locks to srv */ | |
| bool nohandlecache:1; /* disable caching dir handles if srvr probs */ | |
| bool mand_lock:1; /* send mandatory not posix byte range lock reqs */ | |
| bool seal:1; /* request transport encryption on share */ | |
| bool nodfs:1; /* Do not request DFS, even if available */ | |
| bool local_lease:1; /* check leases only on local system, not remote */ | |
| bool noblocksnd:1; | |
| bool noautotune:1; | |
| bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ | |
| bool no_lease:1; /* disable requesting leases */ | |
| bool no_sparse:1; /* do not attempt to set files sparse */ | |
| bool fsc:1; /* enable fscache */ | |
| bool mfsymlinks:1; /* use Minshall+French Symlinks */ | |
| bool multiuser:1; | |
| bool rwpidforward:1; /* pid forward for read/write operations */ | |
| bool nosharesock:1; | |
| bool persistent:1; | |
| bool nopersistent:1; | |
| bool resilient:1; /* noresilient not required since not fored for CA */ | |
| bool domainauto:1; | |
| bool rdma:1; | |
| bool multichannel:1; | |
| bool multichannel_specified:1; /* true if user specified multichannel or nomultichannel */ | |
| bool max_channels_specified:1; /* true if user specified max_channels */ | |
| bool use_client_guid:1; | |
| /* reuse existing guid for multichannel */ | |
| u8 client_guid[SMB2_CLIENT_GUID_SIZE]; | |
| /* User-specified original r/wsize value */ | |
| unsigned int vol_rsize; | |
| unsigned int vol_wsize; | |
| unsigned int bsize; | |
| unsigned int rasize; | |
| unsigned int rsize; | |
| unsigned int wsize; | |
| unsigned int min_offload; | |
| unsigned int retrans; | |
| bool sockopt_tcp_nodelay:1; | |
| /* attribute cache timeout for files and directories in jiffies */ | |
| unsigned long acregmax; | |
| unsigned long acdirmax; | |
| /* timeout for deferred close of files in jiffies */ | |
| unsigned long closetimeo; | |
| struct smb_version_operations *ops; | |
| struct smb_version_values *vals; | |
| char *prepath; | |
| struct sockaddr_storage dstaddr; /* destination address */ | |
| struct sockaddr_storage srcaddr; /* allow binding to a local IP */ | |
| struct nls_table *local_nls; /* This is a copy of the pointer in cifs_sb */ | |
| unsigned int echo_interval; /* echo interval in secs */ | |
| __u64 snapshot_time; /* needed for timewarp tokens */ | |
| __u32 handle_timeout; /* persistent and durable handle timeout in ms */ | |
| unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ | |
| unsigned int max_channels; | |
| unsigned int max_cached_dirs; | |
| bool compress; /* enable SMB2 messages (READ/WRITE) de/compression */ | |
| bool rootfs:1; /* if it's a SMB root file system */ | |
| bool witness:1; /* use witness protocol */ | |
| int unicode; | |
| char *leaf_fullpath; | |
| struct cifs_ses *dfs_root_ses; | |
| bool dfs_automount:1; /* set for dfs automount only */ | |
| enum cifs_reparse_type reparse_type; | |
| enum cifs_symlink_type symlink_type; | |
| bool nonativesocket:1; | |
| bool dfs_conn:1; /* set for dfs mounts */ | |
| char *dns_dom; | |
| char *symlinkroot; /* top level directory for native SMB symlinks in absolute format */ | |
| }; | |
| extern const struct fs_parameter_spec smb3_fs_parameters[]; | |
| static inline enum cifs_symlink_type cifs_symlink_type(struct cifs_sb_info *cifs_sb) | |
| { | |
| bool posix = cifs_sb_master_tcon(cifs_sb)->posix_extensions; | |
| if (cifs_sb->ctx->symlink_type != CIFS_SYMLINK_TYPE_DEFAULT) | |
| return cifs_sb->ctx->symlink_type; | |
| if (cifs_sb->ctx->mfsymlinks) | |
| return CIFS_SYMLINK_TYPE_MFSYMLINKS; | |
| else if (cifs_sb->ctx->sfu_emul) | |
| return CIFS_SYMLINK_TYPE_SFU; | |
| else if (cifs_sb->ctx->linux_ext && !cifs_sb->ctx->no_linux_ext) | |
| return posix ? CIFS_SYMLINK_TYPE_NATIVE : CIFS_SYMLINK_TYPE_UNIX; | |
| else if (cifs_sb->ctx->reparse_type != CIFS_REPARSE_TYPE_NONE) | |
| return CIFS_SYMLINK_TYPE_NATIVE; | |
| return CIFS_SYMLINK_TYPE_NONE; | |
| } | |
| int smb3_init_fs_context(struct fs_context *fc); | |
| void smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx); | |
| void smb3_cleanup_fs_context(struct smb3_fs_context *ctx); | |
| static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *fc) | |
| { | |
| return fc->fs_private; | |
| } | |
| int smb3_fs_context_dup(struct smb3_fs_context *new_ctx, | |
| struct smb3_fs_context *ctx); | |
| int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, | |
| struct cifs_ses *ses); | |
| unsigned int smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb); | |
| /* | |
| * max deferred close timeout (jiffies) - 2^30 | |
| */ | |
| #define SMB3_MAX_DCLOSETIMEO (1 << 30) | |
| #define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */ | |
| #define MAX_CACHED_FIDS 16 | |
| char *cifs_sanitize_prepath(char *prepath, gfp_t gfp); | |
| extern struct mutex cifs_mount_mutex; | |
| static inline void cifs_mount_lock(void) | |
| { | |
| mutex_lock(&cifs_mount_mutex); | |
| } | |
| static inline void cifs_mount_unlock(void) | |
| { | |
| mutex_unlock(&cifs_mount_mutex); | |
| } | |
| static inline void cifs_negotiate_rsize(struct TCP_Server_Info *server, | |
| struct smb3_fs_context *ctx, | |
| struct cifs_tcon *tcon) | |
| { | |
| unsigned int size; | |
| size = umax(server->ops->negotiate_rsize(tcon, ctx), PAGE_SIZE); | |
| if (ctx->rsize) | |
| size = umax(umin(ctx->rsize, size), PAGE_SIZE); | |
| ctx->rsize = round_down(size, PAGE_SIZE); | |
| } | |
| static inline void cifs_negotiate_wsize(struct TCP_Server_Info *server, | |
| struct smb3_fs_context *ctx, | |
| struct cifs_tcon *tcon) | |
| { | |
| unsigned int size; | |
| size = umax(server->ops->negotiate_wsize(tcon, ctx), PAGE_SIZE); | |
| if (ctx->wsize) | |
| size = umax(umin(ctx->wsize, size), PAGE_SIZE); | |
| ctx->wsize = round_down(size, PAGE_SIZE); | |
| } | |
| static inline void cifs_negotiate_iosize(struct TCP_Server_Info *server, | |
| struct smb3_fs_context *ctx, | |
| struct cifs_tcon *tcon) | |
| { | |
| cifs_negotiate_rsize(server, ctx, tcon); | |
| cifs_negotiate_wsize(server, ctx, tcon); | |
| } | |
| #endif |