Commit fa9415d4 authored by Namjae Jeon's avatar Namjae Jeon Committed by Steve French
Browse files

ksmbd: mark SMB2_SESSION_EXPIRED to session when destroying previous session



Currently ksmbd exit connection as well destroying previous session.
When testing durable handle feaure, I found that
destroy_previous_session() should destroy only session, i.e. the
connection should be still alive. This patch mark SMB2_SESSION_EXPIRED
on the previous session to be destroyed later and not used anymore.

Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 34cd86b6
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ void ksmbd_session_destroy(struct ksmbd_session *sess)
	kfree(sess);
}

static struct ksmbd_session *__session_lookup(unsigned long long id)
struct ksmbd_session *__session_lookup(unsigned long long id)
{
	struct ksmbd_session *sess;

@@ -305,6 +305,31 @@ struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
	return sess;
}

void destroy_previous_session(struct ksmbd_conn *conn,
			      struct ksmbd_user *user, u64 id)
{
	struct ksmbd_session *prev_sess;
	struct ksmbd_user *prev_user;

	down_write(&sessions_table_lock);
	down_write(&conn->session_lock);
	prev_sess = __session_lookup(id);
	if (!prev_sess || prev_sess->state == SMB2_SESSION_EXPIRED)
		goto out;

	prev_user = prev_sess->user;
	if (!prev_user ||
	    strcmp(user->name, prev_user->name) ||
	    user->passkey_sz != prev_user->passkey_sz ||
	    memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
		goto out;

	prev_sess->state = SMB2_SESSION_EXPIRED;
out:
	up_write(&conn->session_lock);
	up_write(&sessions_table_lock);
}

static bool ksmbd_preauth_session_id_match(struct preauth_session *sess,
					   unsigned long long id)
{
+3 −0
Original line number Diff line number Diff line
@@ -88,8 +88,11 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
int ksmbd_session_register(struct ksmbd_conn *conn,
			   struct ksmbd_session *sess);
void ksmbd_sessions_deregister(struct ksmbd_conn *conn);
struct ksmbd_session *__session_lookup(unsigned long long id);
struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
					       unsigned long long id);
void destroy_previous_session(struct ksmbd_conn *conn,
			      struct ksmbd_user *user, u64 id);
struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
						    u64 sess_id);
struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
+0 −24
Original line number Diff line number Diff line
@@ -607,30 +607,6 @@ int smb2_check_user_session(struct ksmbd_work *work)
	return -ENOENT;
}

static void destroy_previous_session(struct ksmbd_conn *conn,
				     struct ksmbd_user *user, u64 id)
{
	struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id);
	struct ksmbd_user *prev_user;
	struct channel *chann;
	long index;

	if (!prev_sess)
		return;

	prev_user = prev_sess->user;

	if (!prev_user ||
	    strcmp(user->name, prev_user->name) ||
	    user->passkey_sz != prev_user->passkey_sz ||
	    memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
		return;

	prev_sess->state = SMB2_SESSION_EXPIRED;
	xa_for_each(&prev_sess->ksmbd_chann_list, index, chann)
		ksmbd_conn_set_exiting(chann->conn);
}

/**
 * smb2_get_name() - get filename string from on the wire smb format
 * @src:	source buffer