* FAILED: patch "[PATCH] ksmbd: fix race condition between destroy_previous_session()" failed to apply to 6.6-stable tree
@ 2024-08-26 11:38 gregkh
2024-08-27 2:30 ` Namjae Jeon
0 siblings, 1 reply; 3+ messages in thread
From: gregkh @ 2024-08-26 11:38 UTC (permalink / raw)
To: linkinjeon, stfrench; +Cc: stable
The patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x 76e98a158b207771a6c9a0de0a60522a446a3447
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2024082626-succulent-engraver-73cd@gregkh' --subject-prefix 'PATCH 6.6.y' HEAD^..
Possible dependencies:
76e98a158b20 ("ksmbd: fix race condition between destroy_previous_session() and smb2 operations()")
d484d621d40f ("ksmbd: add durable scavenger timer")
c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
fa9415d4024f ("ksmbd: mark SMB2_SESSION_EXPIRED to session when destroying previous session")
c2a721eead71 ("ksmbd: lazy v2 lease break on smb2_write()")
d47d9886aeef ("ksmbd: send v2 lease break notification for directory")
eb547407f357 ("ksmbd: downgrade RWH lease caching state to RH for directory")
2e450920d58b ("ksmbd: move oplock handling after unlock parent dir")
4274a9dc6aeb ("ksmbd: separately allocate ci per dentry")
864fb5d37163 ("ksmbd: fix possible deadlock in smb2_open")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 76e98a158b207771a6c9a0de0a60522a446a3447 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <linkinjeon@kernel.org>
Date: Sat, 17 Aug 2024 14:03:49 +0900
Subject: [PATCH] ksmbd: fix race condition between destroy_previous_session()
and smb2 operations()
If there is ->PreviousSessionId field in the session setup request,
The session of the previous connection should be destroyed.
During this, if the smb2 operation requests in the previous session are
being processed, a racy issue could happen with ksmbd_destroy_file_table().
This patch sets conn->status to KSMBD_SESS_NEED_RECONNECT to block
incoming operations and waits until on-going operations are complete
(i.e. idle) before desctorying the previous session.
Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
Cc: stable@vger.kernel.org # v6.6+
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-25040
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
index 09e1e7771592..7889df8112b4 100644
--- a/fs/smb/server/connection.c
+++ b/fs/smb/server/connection.c
@@ -165,11 +165,43 @@ void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
up_read(&conn_list_lock);
}
-void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
+void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
{
wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
}
+int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id)
+{
+ struct ksmbd_conn *conn;
+ int rc, retry_count = 0, max_timeout = 120;
+ int rcount = 1;
+
+retry_idle:
+ if (retry_count >= max_timeout)
+ return -EIO;
+
+ down_read(&conn_list_lock);
+ list_for_each_entry(conn, &conn_list, conns_list) {
+ if (conn->binding || xa_load(&conn->sessions, sess_id)) {
+ if (conn == curr_conn)
+ rcount = 2;
+ if (atomic_read(&conn->req_running) >= rcount) {
+ rc = wait_event_timeout(conn->req_running_q,
+ atomic_read(&conn->req_running) < rcount,
+ HZ);
+ if (!rc) {
+ up_read(&conn_list_lock);
+ retry_count++;
+ goto retry_idle;
+ }
+ }
+ }
+ }
+ up_read(&conn_list_lock);
+
+ return 0;
+}
+
int ksmbd_conn_write(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h
index 5c2845e47cf2..5b947175c048 100644
--- a/fs/smb/server/connection.h
+++ b/fs/smb/server/connection.h
@@ -145,7 +145,8 @@ extern struct list_head conn_list;
extern struct rw_semaphore conn_list_lock;
bool ksmbd_conn_alive(struct ksmbd_conn *conn);
-void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id);
+void ksmbd_conn_wait_idle(struct ksmbd_conn *conn);
+int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id);
struct ksmbd_conn *ksmbd_conn_alloc(void);
void ksmbd_conn_free(struct ksmbd_conn *conn);
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
index 162a12685d2c..99416ce9f501 100644
--- a/fs/smb/server/mgmt/user_session.c
+++ b/fs/smb/server/mgmt/user_session.c
@@ -311,6 +311,7 @@ void destroy_previous_session(struct ksmbd_conn *conn,
{
struct ksmbd_session *prev_sess;
struct ksmbd_user *prev_user;
+ int err;
down_write(&sessions_table_lock);
down_write(&conn->session_lock);
@@ -325,8 +326,16 @@ void destroy_previous_session(struct ksmbd_conn *conn,
memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
goto out;
+ ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT);
+ err = ksmbd_conn_wait_idle_sess_id(conn, id);
+ if (err) {
+ ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
+ goto out;
+ }
+
ksmbd_destroy_file_table(&prev_sess->file_table);
prev_sess->state = SMB2_SESSION_EXPIRED;
+ ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
ksmbd_launch_ksmbd_durable_scavenger();
out:
up_write(&conn->session_lock);
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 3f4c56a10a86..cb7f487c96af 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2213,7 +2213,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_conn_unlock(conn);
ksmbd_close_session_fds(work);
- ksmbd_conn_wait_idle(conn, sess_id);
+ ksmbd_conn_wait_idle(conn);
/*
* Re-lookup session to validate if session is deleted
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: FAILED: patch "[PATCH] ksmbd: fix race condition between destroy_previous_session()" failed to apply to 6.6-stable tree
2024-08-26 11:38 FAILED: patch "[PATCH] ksmbd: fix race condition between destroy_previous_session()" failed to apply to 6.6-stable tree gregkh
@ 2024-08-27 2:30 ` Namjae Jeon
2024-08-27 12:50 ` Greg KH
0 siblings, 1 reply; 3+ messages in thread
From: Namjae Jeon @ 2024-08-27 2:30 UTC (permalink / raw)
To: gregkh; +Cc: stfrench, stable
[-- Attachment #1: Type: text/plain, Size: 7188 bytes --]
On Mon, Aug 26, 2024 at 8:57 PM <gregkh@linuxfoundation.org> wrote:
>
>
Hi Greg,
> The patch below does not apply to the 6.6-stable tree.
> If someone wants it applied there, or to any other stable or longterm
> tree, then please email the backport, including the original git commit
> id to <stable@vger.kernel.org>.
Could you please apply the attached backport patch for linux 6.6 stable kernel ?
Thanks!
>
> To reproduce the conflict and resubmit, you may use the following commands:
>
> git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
> git checkout FETCH_HEAD
> git cherry-pick -x 76e98a158b207771a6c9a0de0a60522a446a3447
> # <resolve conflicts, build, test, etc.>
> git commit -s
> git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2024082626-succulent-engraver-73cd@gregkh' --subject-prefix 'PATCH 6.6.y' HEAD^..
>
> Possible dependencies:
>
> 76e98a158b20 ("ksmbd: fix race condition between destroy_previous_session() and smb2 operations()")
> d484d621d40f ("ksmbd: add durable scavenger timer")
> c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
> fa9415d4024f ("ksmbd: mark SMB2_SESSION_EXPIRED to session when destroying previous session")
> c2a721eead71 ("ksmbd: lazy v2 lease break on smb2_write()")
> d47d9886aeef ("ksmbd: send v2 lease break notification for directory")
> eb547407f357 ("ksmbd: downgrade RWH lease caching state to RH for directory")
> 2e450920d58b ("ksmbd: move oplock handling after unlock parent dir")
> 4274a9dc6aeb ("ksmbd: separately allocate ci per dentry")
> 864fb5d37163 ("ksmbd: fix possible deadlock in smb2_open")
>
> thanks,
>
> greg k-h
>
> ------------------ original commit in Linus's tree ------------------
>
> From 76e98a158b207771a6c9a0de0a60522a446a3447 Mon Sep 17 00:00:00 2001
> From: Namjae Jeon <linkinjeon@kernel.org>
> Date: Sat, 17 Aug 2024 14:03:49 +0900
> Subject: [PATCH] ksmbd: fix race condition between destroy_previous_session()
> and smb2 operations()
>
> If there is ->PreviousSessionId field in the session setup request,
> The session of the previous connection should be destroyed.
> During this, if the smb2 operation requests in the previous session are
> being processed, a racy issue could happen with ksmbd_destroy_file_table().
> This patch sets conn->status to KSMBD_SESS_NEED_RECONNECT to block
> incoming operations and waits until on-going operations are complete
> (i.e. idle) before desctorying the previous session.
>
> Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
> Cc: stable@vger.kernel.org # v6.6+
> Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-25040
> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
> Signed-off-by: Steve French <stfrench@microsoft.com>
>
> diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
> index 09e1e7771592..7889df8112b4 100644
> --- a/fs/smb/server/connection.c
> +++ b/fs/smb/server/connection.c
> @@ -165,11 +165,43 @@ void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
> up_read(&conn_list_lock);
> }
>
> -void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
> +void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
> {
> wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
> }
>
> +int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id)
> +{
> + struct ksmbd_conn *conn;
> + int rc, retry_count = 0, max_timeout = 120;
> + int rcount = 1;
> +
> +retry_idle:
> + if (retry_count >= max_timeout)
> + return -EIO;
> +
> + down_read(&conn_list_lock);
> + list_for_each_entry(conn, &conn_list, conns_list) {
> + if (conn->binding || xa_load(&conn->sessions, sess_id)) {
> + if (conn == curr_conn)
> + rcount = 2;
> + if (atomic_read(&conn->req_running) >= rcount) {
> + rc = wait_event_timeout(conn->req_running_q,
> + atomic_read(&conn->req_running) < rcount,
> + HZ);
> + if (!rc) {
> + up_read(&conn_list_lock);
> + retry_count++;
> + goto retry_idle;
> + }
> + }
> + }
> + }
> + up_read(&conn_list_lock);
> +
> + return 0;
> +}
> +
> int ksmbd_conn_write(struct ksmbd_work *work)
> {
> struct ksmbd_conn *conn = work->conn;
> diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h
> index 5c2845e47cf2..5b947175c048 100644
> --- a/fs/smb/server/connection.h
> +++ b/fs/smb/server/connection.h
> @@ -145,7 +145,8 @@ extern struct list_head conn_list;
> extern struct rw_semaphore conn_list_lock;
>
> bool ksmbd_conn_alive(struct ksmbd_conn *conn);
> -void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id);
> +void ksmbd_conn_wait_idle(struct ksmbd_conn *conn);
> +int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id);
> struct ksmbd_conn *ksmbd_conn_alloc(void);
> void ksmbd_conn_free(struct ksmbd_conn *conn);
> bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
> diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
> index 162a12685d2c..99416ce9f501 100644
> --- a/fs/smb/server/mgmt/user_session.c
> +++ b/fs/smb/server/mgmt/user_session.c
> @@ -311,6 +311,7 @@ void destroy_previous_session(struct ksmbd_conn *conn,
> {
> struct ksmbd_session *prev_sess;
> struct ksmbd_user *prev_user;
> + int err;
>
> down_write(&sessions_table_lock);
> down_write(&conn->session_lock);
> @@ -325,8 +326,16 @@ void destroy_previous_session(struct ksmbd_conn *conn,
> memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
> goto out;
>
> + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT);
> + err = ksmbd_conn_wait_idle_sess_id(conn, id);
> + if (err) {
> + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
> + goto out;
> + }
> +
> ksmbd_destroy_file_table(&prev_sess->file_table);
> prev_sess->state = SMB2_SESSION_EXPIRED;
> + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
> ksmbd_launch_ksmbd_durable_scavenger();
> out:
> up_write(&conn->session_lock);
> diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
> index 3f4c56a10a86..cb7f487c96af 100644
> --- a/fs/smb/server/smb2pdu.c
> +++ b/fs/smb/server/smb2pdu.c
> @@ -2213,7 +2213,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
> ksmbd_conn_unlock(conn);
>
> ksmbd_close_session_fds(work);
> - ksmbd_conn_wait_idle(conn, sess_id);
> + ksmbd_conn_wait_idle(conn);
>
> /*
> * Re-lookup session to validate if session is deleted
>
[-- Attachment #2: 0001-ksmbd-fix-race-condition-between-destroy_previous_se.patch --]
[-- Type: application/x-patch, Size: 4777 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: FAILED: patch "[PATCH] ksmbd: fix race condition between destroy_previous_session()" failed to apply to 6.6-stable tree
2024-08-27 2:30 ` Namjae Jeon
@ 2024-08-27 12:50 ` Greg KH
0 siblings, 0 replies; 3+ messages in thread
From: Greg KH @ 2024-08-27 12:50 UTC (permalink / raw)
To: Namjae Jeon; +Cc: stfrench, stable
On Tue, Aug 27, 2024 at 11:30:15AM +0900, Namjae Jeon wrote:
> On Mon, Aug 26, 2024 at 8:57 PM <gregkh@linuxfoundation.org> wrote:
> >
> >
> Hi Greg,
>
> > The patch below does not apply to the 6.6-stable tree.
> > If someone wants it applied there, or to any other stable or longterm
> > tree, then please email the backport, including the original git commit
> > id to <stable@vger.kernel.org>.
> Could you please apply the attached backport patch for linux 6.6 stable kernel ?
Now applied, thanks.
greg k-h
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-08-27 12:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-26 11:38 FAILED: patch "[PATCH] ksmbd: fix race condition between destroy_previous_session()" failed to apply to 6.6-stable tree gregkh
2024-08-27 2:30 ` Namjae Jeon
2024-08-27 12:50 ` Greg KH
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox