linux/fs/smb/client/smb2ops.c

// SPDX-License-Identifier: GPL-2.0
/*
 *  SMB2 version specific operations
 *
 *  Copyright (c) 2012, Jeff Layton <[email protected]>
 */

#include <linux/pagemap.h>
#include <linux/vfs.h>
#include <linux/falloc.h>
#include <linux/scatterlist.h>
#include <linux/uuid.h>
#include <linux/sort.h>
#include <crypto/aead.h>
#include <linux/fiemap.h>
#include <uapi/linux/magic.h>
#include "cifsfs.h"
#include "cifsglob.h"
#include "smb2pdu.h"
#include "smb2proto.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifs_unicode.h"
#include "smb2status.h"
#include "smb2glob.h"
#include "cifs_ioctl.h"
#include "smbdirect.h"
#include "fscache.h"
#include "fs_context.h"
#include "cached_dir.h"
#include "reparse.h"

/* Change credits for different ops and return the total number of credits */
static int
change_conf(struct TCP_Server_Info *server)
{}

static void
smb2_add_credits(struct TCP_Server_Info *server,
		 struct cifs_credits *credits, const int optype)
{}

static void
smb2_set_credits(struct TCP_Server_Info *server, const int val)
{}

static int *
smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
{}

static unsigned int
smb2_get_credits(struct mid_q_entry *mid)
{}

static int
smb2_wait_mtu_credits(struct TCP_Server_Info *server, size_t size,
		      size_t *num, struct cifs_credits *credits)
{}

static int
smb2_adjust_credits(struct TCP_Server_Info *server,
		    struct cifs_io_subrequest *subreq,
		    unsigned int /*enum smb3_rw_credits_trace*/ trace)
{}

static __u64
smb2_get_next_mid(struct TCP_Server_Info *server)
{}

static void
smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
{}

static struct mid_q_entry *
__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
{}

static struct mid_q_entry *
smb2_find_mid(struct TCP_Server_Info *server, char *buf)
{}

static struct mid_q_entry *
smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf)
{}

static void
smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
{}

static bool
smb2_need_neg(struct TCP_Server_Info *server)
{}

static int
smb2_negotiate(const unsigned int xid,
	       struct cifs_ses *ses,
	       struct TCP_Server_Info *server)
{}

static unsigned int
smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
{}

static unsigned int
smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
{}

static unsigned int
smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
{}

static unsigned int
smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
{}

/*
 * compare two interfaces a and b
 * return 0 if everything matches.
 * return 1 if a is rdma capable, or rss capable, or has higher link speed
 * return -1 otherwise.
 */
static int
iface_cmp(struct cifs_server_iface *a, struct cifs_server_iface *b)
{}

static int
parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
			size_t buf_len, struct cifs_ses *ses, bool in_mount)
{}

int
SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount)
{}

static void
smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
	      struct cifs_sb_info *cifs_sb)
{}

static void
smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
	      struct cifs_sb_info *cifs_sb)
{}

static int
smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
			struct cifs_sb_info *cifs_sb, const char *full_path)
{}

static int smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
			     struct cifs_sb_info *cifs_sb, const char *full_path,
			     u64 *uniqueid, struct cifs_open_info_data *data)
{}

static int smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
				struct cifsFileInfo *cfile, struct cifs_open_info_data *data)
{}

#ifdef CONFIG_CIFS_XATTR
static ssize_t
move_smb2_ea_to_cifs(char *dst, size_t dst_size,
		     struct smb2_file_full_ea_info *src, size_t src_size,
		     const unsigned char *ea_name)
{}

static ssize_t
smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
	       const unsigned char *path, const unsigned char *ea_name,
	       char *ea_data, size_t buf_size,
	       struct cifs_sb_info *cifs_sb)
{}

static int
smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
	    const char *path, const char *ea_name, const void *ea_value,
	    const __u16 ea_value_len, const struct nls_table *nls_codepage,
	    struct cifs_sb_info *cifs_sb)
{}
#endif

static bool
smb2_can_echo(struct TCP_Server_Info *server)
{}

static void
smb2_clear_stats(struct cifs_tcon *tcon)
{}

static void
smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon)
{}

static void
smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
{}

static void
smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
{}

static int
smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon,
		struct cifs_fid *fid)
{}

static int
smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
		   struct cifsFileInfo *cfile)
{}

static int
SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
		     u64 persistent_fid, u64 volatile_fid,
		     struct copychunk_ioctl *pcchunk)
{}

static int
smb2_ioctl_query_info(const unsigned int xid,
		      struct cifs_tcon *tcon,
		      struct cifs_sb_info *cifs_sb,
		      __le16 *path, int is_dir,
		      unsigned long p)
{}

static ssize_t
smb2_copychunk_range(const unsigned int xid,
			struct cifsFileInfo *srcfile,
			struct cifsFileInfo *trgtfile, u64 src_off,
			u64 len, u64 dest_off)
{}

static int
smb2_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
		struct cifs_fid *fid)
{}

static unsigned int
smb2_read_data_offset(char *buf)
{}

static unsigned int
smb2_read_data_length(char *buf, bool in_remaining)
{}


static int
smb2_sync_read(const unsigned int xid, struct cifs_fid *pfid,
	       struct cifs_io_parms *parms, unsigned int *bytes_read,
	       char **buf, int *buf_type)
{}

static int
smb2_sync_write(const unsigned int xid, struct cifs_fid *pfid,
		struct cifs_io_parms *parms, unsigned int *written,
		struct kvec *iov, unsigned long nr_segs)
{}

/* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */
static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
		struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse)
{}

static int
smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
		   struct cifsFileInfo *cfile, __u64 size, bool set_alloc)
{}

static int
smb2_duplicate_extents(const unsigned int xid,
			struct cifsFileInfo *srcfile,
			struct cifsFileInfo *trgtfile, u64 src_off,
			u64 len, u64 dest_off)
{}

static int
smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
		   struct cifsFileInfo *cfile)
{}

static int
smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
		   struct cifsFileInfo *cfile)
{}

/* GMT Token is @GMT-YYYY.MM.DD-HH.MM.SS Unicode which is 48 bytes + null */
#define GMT_TOKEN_SIZE

#define MIN_SNAPSHOT_ARRAY_SIZE

/*
 * Input buffer contains (empty) struct smb_snapshot array with size filled in
 * For output see struct SRV_SNAPSHOT_ARRAY in MS-SMB2 section 2.2.32.2
 */
static int
smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
		   struct cifsFileInfo *cfile, void __user *ioc_buf)
{}



static int
smb3_notify(const unsigned int xid, struct file *pfile,
	    void __user *ioc_buf, bool return_changes)
{}

static int
smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
		     const char *path, struct cifs_sb_info *cifs_sb,
		     struct cifs_fid *fid, __u16 search_flags,
		     struct cifs_search_info *srch_inf)
{}

static int
smb2_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon,
		    struct cifs_fid *fid, __u16 search_flags,
		    struct cifs_search_info *srch_inf)
{}

static int
smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
	       struct cifs_fid *fid)
{}

/*
 * If we negotiate SMB2 protocol and get STATUS_PENDING - update
 * the number of credits and return true. Otherwise - return false.
 */
static bool
smb2_is_status_pending(char *buf, struct TCP_Server_Info *server)
{}

static bool
smb2_is_session_expired(char *buf)
{}

static bool
smb2_is_status_io_timeout(char *buf)
{}

static bool
smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
{}

static int
smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
		__u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
{}

void
smb2_set_replay(struct TCP_Server_Info *server, struct smb_rqst *rqst)
{}

void
smb2_set_related(struct smb_rqst *rqst)
{}

char smb2_padding[7] =;

void
smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
{}

/*
 * helper function for exponential backoff and check if replayable
 */
bool smb2_should_replay(struct cifs_tcon *tcon,
				int *pretries,
				int *pcur_sleep)
{}

/*
 * Passes the query info response back to the caller on success.
 * Caller need to free this with free_rsp_buf().
 */
int
smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
			 const char *path, u32 desired_access,
			 u32 class, u32 type, u32 output_len,
			 struct kvec *rsp, int *buftype,
			 struct cifs_sb_info *cifs_sb)
{}

static int
smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
	     struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
{}

static int
smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
	       struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
{}

static bool
smb2_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
{}

static int
smb2_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
	       __u64 length, __u32 type, int lock, int unlock, bool wait)
{}

static void
smb2_get_lease_key(struct inode *inode, struct cifs_fid *fid)
{}

static void
smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
{}

static void
smb2_new_lease_key(struct cifs_fid *fid)
{}

static int
smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
		   const char *search_name,
		   struct dfs_info3_param **target_nodes,
		   unsigned int *num_of_nodes,
		   const struct nls_table *nls_codepage, int remap)
{}

static struct cifs_ntsd *
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
		    const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
{}

static struct cifs_ntsd *
get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
		     const char *path, u32 *pacllen, u32 info)
{}

static int
set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
		struct inode *inode, const char *path, int aclflag)
{}

/* Retrieve an ACL from the server */
static struct cifs_ntsd *
get_smb2_acl(struct cifs_sb_info *cifs_sb,
	     struct inode *inode, const char *path,
	     u32 *pacllen, u32 info)
{}

static long smb3_zero_data(struct file *file, struct cifs_tcon *tcon,
			     loff_t offset, loff_t len, unsigned int xid)
{}

static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
			    loff_t offset, loff_t len, bool keep_size)
{}

static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
			    loff_t offset, loff_t len)
{}

static int smb3_simple_fallocate_write_range(unsigned int xid,
					     struct cifs_tcon *tcon,
					     struct cifsFileInfo *cfile,
					     loff_t off, loff_t len,
					     char *buf)
{}

static int smb3_simple_fallocate_range(unsigned int xid,
				       struct cifs_tcon *tcon,
				       struct cifsFileInfo *cfile,
				       loff_t off, loff_t len)
{}


static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
			    loff_t off, loff_t len, bool keep_size)
{}

static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
			    loff_t off, loff_t len)
{}

static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
			      loff_t off, loff_t len)
{}

static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offset, int whence)
{}

static int smb3_fiemap(struct cifs_tcon *tcon,
		       struct cifsFileInfo *cfile,
		       struct fiemap_extent_info *fei, u64 start, u64 len)
{}

static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
			   loff_t off, loff_t len)
{}

static void
smb2_downgrade_oplock(struct TCP_Server_Info *server,
		      struct cifsInodeInfo *cinode, __u32 oplock,
		      unsigned int epoch, bool *purge_cache)
{}

static void
smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
		       unsigned int epoch, bool *purge_cache);

static void
smb3_downgrade_oplock(struct TCP_Server_Info *server,
		       struct cifsInodeInfo *cinode, __u32 oplock,
		       unsigned int epoch, bool *purge_cache)
{}

static void
smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
		      unsigned int epoch, bool *purge_cache)
{}

static void
smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
		       unsigned int epoch, bool *purge_cache)
{}

static void
smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
		      unsigned int epoch, bool *purge_cache)
{}

#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
static bool
smb2_is_read_op(__u32 oplock)
{}
#endif /* CIFS_ALLOW_INSECURE_LEGACY */

static bool
smb21_is_read_op(__u32 oplock)
{}

static __le32
map_oplock_to_lease(u8 oplock)
{}

static char *
smb2_create_lease_buf(u8 *lease_key, u8 oplock)
{}

static char *
smb3_create_lease_buf(u8 *lease_key, u8 oplock)
{}

static __u8
smb2_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key)
{}

static __u8
smb3_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key)
{}

static unsigned int
smb2_wp_retry_size(struct inode *inode)
{}

static bool
smb2_dir_needs_close(struct cifsFileInfo *cfile)
{}

static void
fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
		   struct smb_rqst *old_rq, __le16 cipher_type)
{}

static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct smb_rqst *rqst,
				 int num_rqst, const u8 *sig, u8 **iv,
				 struct aead_request **req, struct sg_table *sgt,
				 unsigned int *num_sgs, size_t *sensitive_size)
{}

static void *smb2_get_aead_req(struct crypto_aead *tfm, struct smb_rqst *rqst,
			       int num_rqst, const u8 *sig, u8 **iv,
			       struct aead_request **req, struct scatterlist **sgl,
			       size_t *sensitive_size)
{}

static int
smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
{}
/*
 * Encrypt or decrypt @rqst message. @rqst[0] has the following format:
 * iov[0]   - transform header (associate data),
 * iov[1-N] - SMB2 header and pages - data to encrypt.
 * On success return encrypted data in iov[1-N] and pages, leave iov[0]
 * untouched.
 */
static int
crypt_message(struct TCP_Server_Info *server, int num_rqst,
	      struct smb_rqst *rqst, int enc)
{}

/*
 * Clear a read buffer, discarding the folios which have XA_MARK_0 set.
 */
static void cifs_clear_xarray_buffer(struct xarray *buffer)
{}

void
smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst)
{}

/*
 * This function will initialize new_rq and encrypt the content.
 * The first entry, new_rq[0], only contains a single iov which contains
 * a smb2_transform_hdr and is pre-allocated by the caller.
 * This function then populates new_rq[1+] with the content from olq_rq[0+].
 *
 * The end result is an array of smb_rqst structures where the first structure
 * only contains a single iov for the transform header which we then can pass
 * to crypt_message().
 *
 * new_rq[0].rq_iov[0] :  smb2_transform_hdr pre-allocated by the caller
 * new_rq[1+].rq_iov[*] == old_rq[0+].rq_iov[*] : SMB2/3 requests
 */
static int
smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
		       struct smb_rqst *new_rq, struct smb_rqst *old_rq)
{}

static int
smb3_is_transform_hdr(void *buf)
{}

static int
decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
		 unsigned int buf_data_size, struct iov_iter *iter,
		 bool is_offloaded)
{}

static int
cifs_copy_pages_to_iter(struct xarray *pages, unsigned int data_size,
			unsigned int skip, struct iov_iter *iter)
{}

static int
handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
		 char *buf, unsigned int buf_len, struct xarray *pages,
		 unsigned int pages_len, bool is_offloaded)
{}

struct smb2_decrypt_work {};


static void smb2_decrypt_offload(struct work_struct *work)
{}


static int
receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
		       int *num_mids)
{}

static int
receive_encrypted_standard(struct TCP_Server_Info *server,
			   struct mid_q_entry **mids, char **bufs,
			   int *num_mids)
{}

static int
smb3_receive_transform(struct TCP_Server_Info *server,
		       struct mid_q_entry **mids, char **bufs, int *num_mids)
{}

int
smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{}

static int smb2_next_header(struct TCP_Server_Info *server, char *buf,
			    unsigned int *noff)
{}

static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
				struct dentry *dentry, struct cifs_tcon *tcon,
				const char *full_path, umode_t mode, dev_t dev)
{}

int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
		       struct dentry *dentry, struct cifs_tcon *tcon,
		       const char *full_path, umode_t mode, dev_t dev)
{}

static int smb2_make_node(unsigned int xid, struct inode *inode,
			  struct dentry *dentry, struct cifs_tcon *tcon,
			  const char *full_path, umode_t mode, dev_t dev)
{}

#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
struct smb_version_operations smb20_operations =;
#endif /* CIFS_ALLOW_INSECURE_LEGACY */

struct smb_version_operations smb21_operations =;

struct smb_version_operations smb30_operations =;

struct smb_version_operations smb311_operations =;

#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
struct smb_version_values smb20_values =;
#endif /* ALLOW_INSECURE_LEGACY */

struct smb_version_values smb21_values =;

struct smb_version_values smb3any_values =;

struct smb_version_values smbdefault_values =;

struct smb_version_values smb30_values =;

struct smb_version_values smb302_values =;

struct smb_version_values smb311_values =;