Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f48558e authored by Shirish Pargaonkar's avatar Shirish Pargaonkar Committed by Steve French
Browse files

cifs: Send a logoff request before removing a smb session



Send a smb session logoff request before removing smb session off of the list.
On a signed smb session, remvoing a session off of the list before sending
a logoff request results in server returning an error for lack of
smb signature.

Never seen an error during smb logoff, so as per MS-SMB2 3.2.5.1,
not sure how an error during logoff should be retried. So for now,
if a server returns an error to a logoff request, log the error and
remove the session off of the list.

Signed-off-by: default avatarShirish Pargaonkar <shirishpargaonkar@gmail.com>
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 3d378d3f
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -2242,6 +2242,8 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)

	spin_lock(&cifs_tcp_ses_lock);
	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
		if (ses->status == CifsExiting)
			continue;
		if (!match_session(ses, vol))
			continue;
		++ses->ses_count;
@@ -2255,24 +2257,37 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
static void
cifs_put_smb_ses(struct cifs_ses *ses)
{
	unsigned int xid;
	unsigned int rc, xid;
	struct TCP_Server_Info *server = ses->server;

	cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);

	spin_lock(&cifs_tcp_ses_lock);
	if (ses->status == CifsExiting) {
		spin_unlock(&cifs_tcp_ses_lock);
		return;
	}
	if (--ses->ses_count > 0) {
		spin_unlock(&cifs_tcp_ses_lock);
		return;
	}

	list_del_init(&ses->smb_ses_list);
	if (ses->status == CifsGood)
		ses->status = CifsExiting;
	spin_unlock(&cifs_tcp_ses_lock);

	if (ses->status == CifsGood && server->ops->logoff) {
	if (ses->status == CifsExiting && server->ops->logoff) {
		xid = get_xid();
		server->ops->logoff(xid, ses);
		rc = server->ops->logoff(xid, ses);
		if (rc)
			cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
				__func__, rc);
		_free_xid(xid);
	}

	spin_lock(&cifs_tcp_ses_lock);
	list_del_init(&ses->smb_ses_list);
	spin_unlock(&cifs_tcp_ses_lock);

	sesInfoFree(ses);
	cifs_put_tcp_session(server);
}
+8 −2
Original line number Diff line number Diff line
@@ -516,13 +516,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
		return -EAGAIN;
	}

	if (ses->status != CifsGood) {
		/* check if SMB2 session is bad because we are setting it up */
	if (ses->status == CifsNew) {
		if ((buf->Command != SMB2_SESSION_SETUP) &&
		    (buf->Command != SMB2_NEGOTIATE))
			return -EAGAIN;
		/* else ok - we are setting up session */
	}

	if (ses->status == CifsExiting) {
		if (buf->Command != SMB2_LOGOFF)
			return -EAGAIN;
		/* else ok - we are shutting down the session */
	}

	*mid = smb2_mid_entry_alloc(buf, ses->server);
	if (*mid == NULL)
		return -ENOMEM;
+9 −2
Original line number Diff line number Diff line
@@ -431,13 +431,20 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
		return -EAGAIN;
	}

	if (ses->status != CifsGood) {
		/* check if SMB session is bad because we are setting it up */
	if (ses->status == CifsNew) {
		if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
			(in_buf->Command != SMB_COM_NEGOTIATE))
			return -EAGAIN;
		/* else ok - we are setting up session */
	}

	if (ses->status == CifsExiting) {
		/* check if SMB session is bad because we are setting it up */
		if (in_buf->Command != SMB_COM_LOGOFF_ANDX)
			return -EAGAIN;
		/* else ok - we are shutting down session */
	}

	*ppmidQ = AllocMidQEntry(in_buf, ses->server);
	if (*ppmidQ == NULL)
		return -ENOMEM;