Commit 6d9b5f6b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'v6.16-rc-part1-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client updates from Steve French:

 - multichannel fixes (mostly reconnect related), and clarification of
   locking documentation

 - automount null pointer check fix

 - fixes to add support for ParentLeaseKey

 - minor cleanup

 - smb1/cifs fixes

* tag 'v6.16-rc-part1-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: update the lock ordering comments with new mutex
  cifs: dns resolution is needed only for primary channel
  cifs: update dstaddr whenever channel iface is updated
  cifs: reset connections for all channels when reconnect requested
  smb: client: use ParentLeaseKey in cifs_do_create
  smb: client: use ParentLeaseKey in open_cached_dir
  smb: client: add ParentLeaseKey support
  cifs: Fix cifs_query_path_info() for Windows NT servers
  cifs: Fix validation of SMB1 query reparse point response
  cifs: Correctly set SMB1 SessionKey field in Session Setup Request
  cifs: Fix encoding of SMB1 Session Setup NTLMSSP Request in non-UNICODE mode
  smb: client: add NULL check in automount_fullpath
  smb: client: Remove an unused function and variable
parents 3c727285 8a5ebd2b
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -155,6 +155,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
	struct cached_fids *cfids;
	const char *npath;
	int retries = 0, cur_sleep = 1;
	__le32 lease_flags = 0;

	if (cifs_sb->root == NULL)
		return -ENOENT;
@@ -201,6 +202,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
	}
	spin_unlock(&cfids->cfid_list_lock);

	pfid = &cfid->fid;

	/*
	 * Skip any prefix paths in @path as lookup_noperm_positive_unlocked() ends up
	 * calling ->lookup() which already adds those through
@@ -222,6 +225,25 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
			rc = -ENOENT;
			goto out;
		}
		if (dentry->d_parent && server->dialect >= SMB30_PROT_ID) {
			struct cached_fid *parent_cfid;

			spin_lock(&cfids->cfid_list_lock);
			list_for_each_entry(parent_cfid, &cfids->entries, entry) {
				if (parent_cfid->dentry == dentry->d_parent) {
					cifs_dbg(FYI, "found a parent cached file handle\n");
					if (parent_cfid->has_lease && parent_cfid->time) {
						lease_flags
							|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
						memcpy(pfid->parent_lease_key,
						       parent_cfid->fid.lease_key,
						       SMB2_LEASE_KEY_SIZE);
					}
					break;
				}
			}
			spin_unlock(&cfids->cfid_list_lock);
		}
	}
	cfid->dentry = dentry;
	cfid->tcon = tcon;
@@ -236,7 +258,6 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
	if (smb3_encryption_required(tcon))
		flags |= CIFS_TRANSFORM_REQ;

	pfid = &cfid->fid;
	server->ops->new_lease_key(pfid);

	memset(rqst, 0, sizeof(rqst));
@@ -256,6 +277,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
				   FILE_READ_EA,
		.disposition = FILE_OPEN,
		.fid = pfid,
		.lease_flags = lease_flags,
		.replay = !!(retries),
	};

+0 −1
Original line number Diff line number Diff line
@@ -70,7 +70,6 @@ bool require_gcm_256; /* false by default */
bool enable_negotiate_signing; /* false by default */
unsigned int global_secflags = CIFSSEC_DEF;
/* unsigned int ntlmv2_support = 0; */
unsigned int sign_CIFS_PDUs = 1;

/*
 * Global transaction id (XID) information
+12 −6
Original line number Diff line number Diff line
@@ -556,7 +556,7 @@ struct smb_version_operations {
	void (*set_oplock_level)(struct cifsInodeInfo *cinode, __u32 oplock, __u16 epoch,
				 bool *purge_cache);
	/* create lease context buffer for CREATE request */
	char * (*create_lease_buf)(u8 *lease_key, u8 oplock);
	char * (*create_lease_buf)(u8 *lease_key, u8 oplock, u8 *parent_lease_key, __le32 le_flags);
	/* parse lease context buffer and return oplock/epoch info */
	__u8 (*parse_lease_buf)(void *buf, __u16 *epoch, char *lkey);
	ssize_t (*copychunk_range)(const unsigned int,
@@ -773,6 +773,7 @@ struct TCP_Server_Info {
	char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
	__u32 sequence_number; /* for signing, protected by srv_mutex */
	__u32 reconnect_instance; /* incremented on each reconnect */
	__le32 session_key_id; /* retrieved from negotiate response and send in session setup request */
	struct session_key session_key;
	unsigned long lstrp; /* when we got last response from this server */
	struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */
@@ -1441,6 +1442,7 @@ struct cifs_open_parms {
	bool reconnect:1;
	bool replay:1; /* indicates that this open is for a replay */
	struct kvec *ea_cctx;
	__le32 lease_flags;
};

struct cifs_fid {
@@ -1448,6 +1450,7 @@ struct cifs_fid {
	__u64 persistent_fid;	/* persist file id for smb2 */
	__u64 volatile_fid;	/* volatile file id for smb2 */
	__u8 lease_key[SMB2_LEASE_KEY_SIZE];	/* lease key for smb2 */
	__u8 parent_lease_key[SMB2_LEASE_KEY_SIZE];
	__u8 create_guid[16];
	__u32 access;
	struct cifs_pending_open *pending_open;
@@ -1989,7 +1992,6 @@ require use of the stronger protocol */
 * reconnect_mutex
 * TCP_Server_Info->srv_mutex	TCP_Server_Info			cifs_get_tcp_session
 * cifs_ses->session_mutex	cifs_ses			sesInfoAlloc
 *				cifs_tcon
 * cifs_tcon->open_file_lock	cifs_tcon->openFileList		tconInfoAlloc
 *				cifs_tcon->pending_opens
 * cifs_tcon->stat_lock		cifs_tcon->bytes_read		tconInfoAlloc
@@ -2008,13 +2010,15 @@ require use of the stronger protocol */
 *				->oplock_credits
 *				->reconnect_instance
 * cifs_ses->ses_lock		(anything that is not protected by another lock and can change)
 *								sesInfoAlloc
 * cifs_ses->iface_lock		cifs_ses->iface_list		sesInfoAlloc
 *				->iface_count
 *				->iface_last_update
 * cifs_ses->chan_lock		cifs_ses->chans
 * cifs_ses->chan_lock		cifs_ses->chans			sesInfoAlloc
 *				->chans_need_reconnect
 *				->chans_in_reconnect
 * cifs_tcon->tc_lock		(anything that is not protected by another lock and can change)
 *								tcon_info_alloc
 * inode->i_rwsem, taken by fs/netfs/locking.c e.g. should be taken before cifsInodeInfo locks
 * cifsInodeInfo->open_file_lock	cifsInodeInfo->openFileList	cifs_alloc_inode
 * cifsInodeInfo->writers_lock	cifsInodeInfo->writers		cifsInodeInfo_alloc
@@ -2022,6 +2026,8 @@ require use of the stronger protocol */
 *				->can_cache_brlcks
 * cifsInodeInfo->deferred_lock	cifsInodeInfo->deferred_closes	cifsInodeInfo_alloc
 * cached_fids->cfid_list_lock	cifs_tcon->cfids->entries	init_cached_dirs
 * cached_fid->fid_lock		(anything that is not protected by another lock and can change)
 *								init_cached_dir
 * cifsFileInfo->fh_mutex	cifsFileInfo			cifs_new_fileinfo
 * cifsFileInfo->file_info_lock	cifsFileInfo->count		cifs_new_fileinfo
 *				->invalidHandle			initiate_cifs_search
+3 −3
Original line number Diff line number Diff line
@@ -597,7 +597,7 @@ typedef union smb_com_session_setup_andx {
		__le16 MaxBufferSize;
		__le16 MaxMpxCount;
		__le16 VcNumber;
		__u32 SessionKey;
		__le32 SessionKey;
		__le16 SecurityBlobLength;
		__u32 Reserved;
		__le32 Capabilities;	/* see below */
@@ -616,7 +616,7 @@ typedef union smb_com_session_setup_andx {
		__le16 MaxBufferSize;
		__le16 MaxMpxCount;
		__le16 VcNumber;
		__u32 SessionKey;
		__le32 SessionKey;
		__le16 CaseInsensitivePasswordLength; /* ASCII password len */
		__le16 CaseSensitivePasswordLength; /* Unicode password length*/
		__u32 Reserved;	/* see below */
@@ -654,7 +654,7 @@ typedef union smb_com_session_setup_andx {
		__le16 MaxBufferSize;
		__le16 MaxMpxCount;
		__le16 VcNumber;
		__u32 SessionKey;
		__le32 SessionKey;
		__le16 PasswordLength;
		__u32 Reserved; /* encrypt key len and offset */
		__le16 ByteCount;
+19 −2
Original line number Diff line number Diff line
@@ -498,6 +498,7 @@ CIFSSMBNegotiate(const unsigned int xid,
	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
	cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
	server->session_key_id = pSMBr->SessionKey;
	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
	server->timeAdj *= 60;

@@ -2753,10 +2754,10 @@ int cifs_query_reparse_point(const unsigned int xid,

	io_req->TotalParameterCount = 0;
	io_req->TotalDataCount = 0;
	io_req->MaxParameterCount = cpu_to_le32(2);
	io_req->MaxParameterCount = cpu_to_le32(0);
	/* BB find exact data count max from sess structure BB */
	io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
	io_req->MaxSetupCount = 4;
	io_req->MaxSetupCount = 1;
	io_req->Reserved = 0;
	io_req->ParameterOffset = 0;
	io_req->DataCount = 0;
@@ -2783,6 +2784,22 @@ int cifs_query_reparse_point(const unsigned int xid,
		goto error;
	}

	/* SetupCount must be 1, otherwise offset to ByteCount is incorrect. */
	if (io_rsp->SetupCount != 1) {
		rc = -EIO;
		goto error;
	}

	/*
	 * ReturnedDataLen is output length of executed IOCTL.
	 * DataCount is output length transferred over network.
	 * Check that we have full FSCTL_GET_REPARSE_POINT buffer.
	 */
	if (data_count != le16_to_cpu(io_rsp->ReturnedDataLen)) {
		rc = -EIO;
		goto error;
	}

	end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
	start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
	if (start >= end) {
Loading