--- /dev/null
+From 3bfbf5f0a99c991769ec562721285df7ab69240b Mon Sep 17 00:00:00 2001
+From: Dudu Lu <phx0fer@gmail.com>
+Date: Mon, 20 Apr 2026 12:40:27 +0800
+Subject: crypto: krb5enc - fix async decrypt skipping hash verification
+
+From: Dudu Lu <phx0fer@gmail.com>
+
+commit 3bfbf5f0a99c991769ec562721285df7ab69240b upstream.
+
+krb5enc_dispatch_decrypt() sets req->base.complete as the skcipher
+callback, which is the caller's own completion handler. When the
+skcipher completes asynchronously, this signals "done" to the caller
+without executing krb5enc_dispatch_decrypt_hash(), completely bypassing
+the integrity verification (hash check).
+
+Compare with the encrypt path which correctly uses
+krb5enc_encrypt_done as an intermediate callback to chain into the
+hash computation on async completion.
+
+Fix by adding krb5enc_decrypt_done as an intermediate callback that
+chains into krb5enc_dispatch_decrypt_hash() upon async skcipher
+completion, matching the encrypt path's callback pattern.
+
+Also fix EBUSY/EINPROGRESS handling throughout: remove
+krb5enc_request_complete() which incorrectly swallowed EINPROGRESS
+notifications that must be passed up to callers waiting on backlogged
+requests, and add missing EBUSY checks in krb5enc_encrypt_ahash_done
+for the dispatch_encrypt return value.
+
+Fixes: d1775a177f7f ("crypto: Add 'krb5enc' hash and cipher AEAD algorithm")
+Signed-off-by: Dudu Lu <phx0fer@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+Unset MAY_BACKLOG on the async completion path so the user won't
+see back-to-back EINPROGRESS notifications.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ crypto/krb5enc.c | 52 +++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 31 insertions(+), 21 deletions(-)
+
+--- a/crypto/krb5enc.c
++++ b/crypto/krb5enc.c
+@@ -39,12 +39,6 @@ struct krb5enc_request_ctx {
+ char tail[];
+ };
+
+-static void krb5enc_request_complete(struct aead_request *req, int err)
+-{
+- if (err != -EINPROGRESS)
+- aead_request_complete(req, err);
+-}
+-
+ /**
+ * crypto_krb5enc_extractkeys - Extract Ke and Ki keys from the key blob.
+ * @keys: Where to put the key sizes and pointers
+@@ -127,7 +121,7 @@ static void krb5enc_encrypt_done(void *d
+ {
+ struct aead_request *req = data;
+
+- krb5enc_request_complete(req, err);
++ aead_request_complete(req, err);
+ }
+
+ /*
+@@ -188,14 +182,16 @@ static void krb5enc_encrypt_ahash_done(v
+ struct ahash_request *ahreq = (void *)(areq_ctx->tail + ictx->reqoff);
+
+ if (err)
+- return krb5enc_request_complete(req, err);
++ goto out;
+
+ krb5enc_insert_checksum(req, ahreq->result);
+
+- err = krb5enc_dispatch_encrypt(req,
+- aead_request_flags(req) & ~CRYPTO_TFM_REQ_MAY_SLEEP);
+- if (err != -EINPROGRESS)
+- aead_request_complete(req, err);
++ err = krb5enc_dispatch_encrypt(req, 0);
++ if (err == -EINPROGRESS)
++ return;
++
++out:
++ aead_request_complete(req, err);
+ }
+
+ /*
+@@ -265,17 +261,16 @@ static void krb5enc_decrypt_hash_done(vo
+ {
+ struct aead_request *req = data;
+
+- if (err)
+- return krb5enc_request_complete(req, err);
+-
+- err = krb5enc_verify_hash(req);
+- krb5enc_request_complete(req, err);
++ if (!err)
++ err = krb5enc_verify_hash(req);
++ aead_request_complete(req, err);
+ }
+
+ /*
+ * Dispatch the hashing of the plaintext after we've done the decryption.
+ */
+-static int krb5enc_dispatch_decrypt_hash(struct aead_request *req)
++static int krb5enc_dispatch_decrypt_hash(struct aead_request *req,
++ unsigned int flags)
+ {
+ struct crypto_aead *krb5enc = crypto_aead_reqtfm(req);
+ struct aead_instance *inst = aead_alg_instance(krb5enc);
+@@ -291,7 +286,7 @@ static int krb5enc_dispatch_decrypt_hash
+ ahash_request_set_tfm(ahreq, auth);
+ ahash_request_set_crypt(ahreq, req->dst, hash,
+ req->assoclen + req->cryptlen - authsize);
+- ahash_request_set_callback(ahreq, aead_request_flags(req),
++ ahash_request_set_callback(ahreq, flags,
+ krb5enc_decrypt_hash_done, req);
+
+ err = crypto_ahash_digest(ahreq);
+@@ -301,6 +296,21 @@ static int krb5enc_dispatch_decrypt_hash
+ return krb5enc_verify_hash(req);
+ }
+
++static void krb5enc_decrypt_done(void *data, int err)
++{
++ struct aead_request *req = data;
++
++ if (err)
++ goto out;
++
++ err = krb5enc_dispatch_decrypt_hash(req, 0);
++ if (err == -EINPROGRESS)
++ return;
++
++out:
++ aead_request_complete(req, err);
++}
++
+ /*
+ * Dispatch the decryption of the ciphertext.
+ */
+@@ -324,7 +334,7 @@ static int krb5enc_dispatch_decrypt(stru
+
+ skcipher_request_set_tfm(skreq, ctx->enc);
+ skcipher_request_set_callback(skreq, aead_request_flags(req),
+- req->base.complete, req->base.data);
++ krb5enc_decrypt_done, req);
+ skcipher_request_set_crypt(skreq, src, dst,
+ req->cryptlen - authsize, req->iv);
+
+@@ -339,7 +349,7 @@ static int krb5enc_decrypt(struct aead_r
+ if (err < 0)
+ return err;
+
+- return krb5enc_dispatch_decrypt_hash(req);
++ return krb5enc_dispatch_decrypt_hash(req, aead_request_flags(req));
+ }
+
+ static int krb5enc_init_tfm(struct crypto_aead *tfm)
--- /dev/null
+From 2ef3bac16fb5e9eee4fb1d722578a79b751ea58a Mon Sep 17 00:00:00 2001
+From: Wesley Atwell <atwellwea@gmail.com>
+Date: Mon, 9 Mar 2026 00:26:24 -0600
+Subject: crypto: krb5enc - fix sleepable flag handling in encrypt dispatch
+
+From: Wesley Atwell <atwellwea@gmail.com>
+
+commit 2ef3bac16fb5e9eee4fb1d722578a79b751ea58a upstream.
+
+krb5enc_encrypt_ahash_done() continues encryption from an ahash
+completion callback by calling krb5enc_dispatch_encrypt().
+
+That helper takes a flags argument for this continuation path, but it
+ignored that argument and reused aead_request_flags(req) when setting
+up the skcipher subrequest callback. This can incorrectly preserve
+CRYPTO_TFM_REQ_MAY_SLEEP when the encrypt step is started from callback
+context.
+
+Preserve the original request flags but clear
+CRYPTO_TFM_REQ_MAY_SLEEP for the callback continuation path, and use
+the caller-supplied flags when setting up the skcipher subrequest.
+
+Fixes: d1775a177f7f ("crypto: Add 'krb5enc' hash and cipher AEAD algorithm")
+Assisted-by: Codex:GPT-5
+Signed-off-by: Wesley Atwell <atwellwea@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ crypto/krb5enc.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/crypto/krb5enc.c
++++ b/crypto/krb5enc.c
+@@ -154,7 +154,7 @@ static int krb5enc_dispatch_encrypt(stru
+ dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, req->assoclen);
+
+ skcipher_request_set_tfm(skreq, enc);
+- skcipher_request_set_callback(skreq, aead_request_flags(req),
++ skcipher_request_set_callback(skreq, flags,
+ krb5enc_encrypt_done, req);
+ skcipher_request_set_crypt(skreq, src, dst, req->cryptlen, req->iv);
+
+@@ -192,7 +192,8 @@ static void krb5enc_encrypt_ahash_done(v
+
+ krb5enc_insert_checksum(req, ahreq->result);
+
+- err = krb5enc_dispatch_encrypt(req, 0);
++ err = krb5enc_dispatch_encrypt(req,
++ aead_request_flags(req) & ~CRYPTO_TFM_REQ_MAY_SLEEP);
+ if (err != -EINPROGRESS)
+ aead_request_complete(req, err);
+ }
--- /dev/null
+From stable+bounces-239935-greg=kroah.com@vger.kernel.org Mon Apr 20 19:59:28 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Apr 2026 12:15:30 -0400
+Subject: ksmbd: fix use-after-free in __ksmbd_close_fd() via durable scavenger
+To: stable@vger.kernel.org
+Cc: Namjae Jeon <linkinjeon@kernel.org>, munan Huang <munanevil@gmail.com>, ChenXiaoSong <chenxiaosong@kylinos.cn>, Steve French <stfrench@microsoft.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260420161531.1241004-1-sashal@kernel.org>
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit 235e32320a470fcd3998fb3774f2290a0eb302a1 ]
+
+When a durable file handle survives session disconnect (TCP close without
+SMB2_LOGOFF), session_fd_check() sets fp->conn = NULL to preserve the
+handle for later reconnection. However, it did not clean up the byte-range
+locks on fp->lock_list.
+
+Later, when the durable scavenger thread times out and calls
+__ksmbd_close_fd(NULL, fp), the lock cleanup loop did:
+
+ spin_lock(&fp->conn->llist_lock);
+
+This caused a slab use-after-free because fp->conn was NULL and the
+original connection object had already been freed by
+ksmbd_tcp_disconnect().
+
+The root cause is asymmetric cleanup: lock entries (smb_lock->clist) were
+left dangling on the freed conn->lock_list while fp->conn was nulled out.
+
+To fix this issue properly, we need to handle the lifetime of
+smb_lock->clist across three paths:
+ - Safely skip clist deletion when list is empty and fp->conn is NULL.
+ - Remove the lock from the old connection's lock_list in
+ session_fd_check()
+ - Re-add the lock to the new connection's lock_list in
+ ksmbd_reopen_durable_fd().
+
+Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
+Co-developed-by: munan Huang <munanevil@gmail.com>
+Signed-off-by: munan Huang <munanevil@gmail.com>
+Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: 49110a8ce654 ("ksmbd: validate owner of durable handle on reconnect")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/vfs_cache.c | 41 ++++++++++++++++++++++++++++++-----------
+ 1 file changed, 30 insertions(+), 11 deletions(-)
+
+--- a/fs/smb/server/vfs_cache.c
++++ b/fs/smb/server/vfs_cache.c
+@@ -463,9 +463,11 @@ static void __ksmbd_close_fd(struct ksmb
+ * there are not accesses to fp->lock_list.
+ */
+ list_for_each_entry_safe(smb_lock, tmp_lock, &fp->lock_list, flist) {
+- spin_lock(&fp->conn->llist_lock);
+- list_del(&smb_lock->clist);
+- spin_unlock(&fp->conn->llist_lock);
++ if (!list_empty(&smb_lock->clist) && fp->conn) {
++ spin_lock(&fp->conn->llist_lock);
++ list_del(&smb_lock->clist);
++ spin_unlock(&fp->conn->llist_lock);
++ }
+
+ list_del(&smb_lock->flist);
+ locks_free_lock(smb_lock->fl);
+@@ -995,6 +997,7 @@ static bool session_fd_check(struct ksmb
+ struct ksmbd_inode *ci;
+ struct oplock_info *op;
+ struct ksmbd_conn *conn;
++ struct ksmbd_lock *smb_lock, *tmp_lock;
+
+ if (!is_reconnectable(fp))
+ return false;
+@@ -1011,6 +1014,12 @@ static bool session_fd_check(struct ksmb
+ }
+ up_write(&ci->m_lock);
+
++ list_for_each_entry_safe(smb_lock, tmp_lock, &fp->lock_list, flist) {
++ spin_lock(&fp->conn->llist_lock);
++ list_del_init(&smb_lock->clist);
++ spin_unlock(&fp->conn->llist_lock);
++ }
++
+ fp->conn = NULL;
+ fp->tcon = NULL;
+ fp->volatile_id = KSMBD_NO_FID;
+@@ -1090,6 +1099,9 @@ int ksmbd_reopen_durable_fd(struct ksmbd
+ {
+ struct ksmbd_inode *ci;
+ struct oplock_info *op;
++ struct ksmbd_conn *conn = work->conn;
++ struct ksmbd_lock *smb_lock;
++ unsigned int old_f_state;
+
+ if (!fp->is_durable || fp->conn || fp->tcon) {
+ pr_err("Invalid durable fd [%p:%p]\n", fp->conn, fp->tcon);
+@@ -1101,9 +1113,23 @@ int ksmbd_reopen_durable_fd(struct ksmbd
+ return -EBADF;
+ }
+
+- fp->conn = work->conn;
++ old_f_state = fp->f_state;
++ fp->f_state = FP_NEW;
++ __open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
++ if (!has_file_id(fp->volatile_id)) {
++ fp->f_state = old_f_state;
++ return -EBADF;
++ }
++
++ fp->conn = conn;
+ fp->tcon = work->tcon;
+
++ list_for_each_entry(smb_lock, &fp->lock_list, flist) {
++ spin_lock(&conn->llist_lock);
++ list_add_tail(&smb_lock->clist, &conn->lock_list);
++ spin_unlock(&conn->llist_lock);
++ }
++
+ ci = fp->f_ci;
+ down_write(&ci->m_lock);
+ list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
+@@ -1114,13 +1140,6 @@ int ksmbd_reopen_durable_fd(struct ksmbd
+ }
+ up_write(&ci->m_lock);
+
+- fp->f_state = FP_NEW;
+- __open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
+- if (!has_file_id(fp->volatile_id)) {
+- fp->conn = NULL;
+- fp->tcon = NULL;
+- return -EBADF;
+- }
+ return 0;
+ }
+
--- /dev/null
+From stable+bounces-239936-greg=kroah.com@vger.kernel.org Mon Apr 20 18:45:52 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Apr 2026 12:15:31 -0400
+Subject: ksmbd: validate owner of durable handle on reconnect
+To: stable@vger.kernel.org
+Cc: Namjae Jeon <linkinjeon@kernel.org>, Davide Ornaghi <d.ornaghi97@gmail.com>, Navaneeth K <knavaneeth786@gmail.com>, Steve French <stfrench@microsoft.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260420161531.1241004-2-sashal@kernel.org>
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit 49110a8ce654bbe56bef7c5e44cce31f4b102b8a ]
+
+Currently, ksmbd does not verify if the user attempting to reconnect
+to a durable handle is the same user who originally opened the file.
+This allows any authenticated user to hijack an orphaned durable handle
+by predicting or brute-forcing the persistent ID.
+
+According to MS-SMB2, the server MUST verify that the SecurityContext
+of the reconnect request matches the SecurityContext associated with
+the existing open.
+Add a durable_owner structure to ksmbd_file to store the original opener's
+UID, GID, and account name. and catpure the owner information when a file
+handle becomes orphaned. and implementing ksmbd_vfs_compare_durable_owner()
+to validate the identity of the requester during SMB2_CREATE (DHnC).
+
+Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
+Reported-by: Davide Ornaghi <d.ornaghi97@gmail.com>
+Reported-by: Navaneeth K <knavaneeth786@gmail.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/mgmt/user_session.c | 8 +--
+ fs/smb/server/oplock.c | 7 +++
+ fs/smb/server/oplock.h | 1
+ fs/smb/server/smb2pdu.c | 3 -
+ fs/smb/server/vfs_cache.c | 87 ++++++++++++++++++++++++++++++++++----
+ fs/smb/server/vfs_cache.h | 12 ++++-
+ 6 files changed, 102 insertions(+), 16 deletions(-)
+
+--- a/fs/smb/server/mgmt/user_session.c
++++ b/fs/smb/server/mgmt/user_session.c
+@@ -382,12 +382,10 @@ void ksmbd_session_destroy(struct ksmbd_
+ return;
+
+ delete_proc_session(sess);
+-
++ ksmbd_tree_conn_session_logoff(sess);
++ ksmbd_destroy_file_table(sess);
+ if (sess->user)
+ ksmbd_free_user(sess->user);
+-
+- ksmbd_tree_conn_session_logoff(sess);
+- ksmbd_destroy_file_table(&sess->file_table);
+ ksmbd_launch_ksmbd_durable_scavenger();
+ ksmbd_session_rpc_clear_list(sess);
+ free_channel_list(sess);
+@@ -618,7 +616,7 @@ void destroy_previous_session(struct ksm
+ goto out;
+ }
+
+- ksmbd_destroy_file_table(&prev_sess->file_table);
++ ksmbd_destroy_file_table(prev_sess);
+ prev_sess->state = SMB2_SESSION_EXPIRED;
+ ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
+ ksmbd_launch_ksmbd_durable_scavenger();
+--- a/fs/smb/server/oplock.c
++++ b/fs/smb/server/oplock.c
+@@ -1841,6 +1841,7 @@ int smb2_check_durable_oplock(struct ksm
+ struct ksmbd_share_config *share,
+ struct ksmbd_file *fp,
+ struct lease_ctx_info *lctx,
++ struct ksmbd_user *user,
+ char *name)
+ {
+ struct oplock_info *opinfo = opinfo_get(fp);
+@@ -1849,6 +1850,12 @@ int smb2_check_durable_oplock(struct ksm
+ if (!opinfo)
+ return 0;
+
++ if (ksmbd_vfs_compare_durable_owner(fp, user) == false) {
++ ksmbd_debug(SMB, "Durable handle reconnect failed: owner mismatch\n");
++ ret = -EBADF;
++ goto out;
++ }
++
+ if (opinfo->is_lease == false) {
+ if (lctx) {
+ pr_err("create context include lease\n");
+--- a/fs/smb/server/oplock.h
++++ b/fs/smb/server/oplock.h
+@@ -126,5 +126,6 @@ int smb2_check_durable_oplock(struct ksm
+ struct ksmbd_share_config *share,
+ struct ksmbd_file *fp,
+ struct lease_ctx_info *lctx,
++ struct ksmbd_user *user,
+ char *name);
+ #endif /* __KSMBD_OPLOCK_H */
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -3013,7 +3013,8 @@ int smb2_open(struct ksmbd_work *work)
+ }
+
+ if (dh_info.reconnected == true) {
+- rc = smb2_check_durable_oplock(conn, share, dh_info.fp, lc, name);
++ rc = smb2_check_durable_oplock(conn, share, dh_info.fp,
++ lc, sess->user, name);
+ if (rc) {
+ ksmbd_put_durable_fd(dh_info.fp);
+ goto err_out2;
+--- a/fs/smb/server/vfs_cache.c
++++ b/fs/smb/server/vfs_cache.c
+@@ -19,6 +19,7 @@
+ #include "misc.h"
+ #include "mgmt/tree_connect.h"
+ #include "mgmt/user_session.h"
++#include "mgmt/user_config.h"
+ #include "smb_common.h"
+ #include "server.h"
+ #include "smb2pdu.h"
+@@ -476,6 +477,8 @@ static void __ksmbd_close_fd(struct ksmb
+
+ if (ksmbd_stream_fd(fp))
+ kfree(fp->stream.name);
++ kfree(fp->owner.name);
++
+ kmem_cache_free(filp_cache, fp);
+ }
+
+@@ -787,11 +790,13 @@ void ksmbd_update_fstate(struct ksmbd_fi
+ }
+
+ static int
+-__close_file_table_ids(struct ksmbd_file_table *ft,
++__close_file_table_ids(struct ksmbd_session *sess,
+ struct ksmbd_tree_connect *tcon,
+ bool (*skip)(struct ksmbd_tree_connect *tcon,
+- struct ksmbd_file *fp))
++ struct ksmbd_file *fp,
++ struct ksmbd_user *user))
+ {
++ struct ksmbd_file_table *ft = &sess->file_table;
+ struct ksmbd_file *fp;
+ unsigned int id = 0;
+ int num = 0;
+@@ -804,7 +809,7 @@ __close_file_table_ids(struct ksmbd_file
+ break;
+ }
+
+- if (skip(tcon, fp) ||
++ if (skip(tcon, fp, sess->user) ||
+ !atomic_dec_and_test(&fp->refcount)) {
+ id++;
+ write_unlock(&ft->lock);
+@@ -856,7 +861,8 @@ static inline bool is_reconnectable(stru
+ }
+
+ static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon,
+- struct ksmbd_file *fp)
++ struct ksmbd_file *fp,
++ struct ksmbd_user *user)
+ {
+ return fp->tcon != tcon;
+ }
+@@ -991,8 +997,62 @@ void ksmbd_stop_durable_scavenger(void)
+ kthread_stop(server_conf.dh_task);
+ }
+
++/*
++ * ksmbd_vfs_copy_durable_owner - Copy owner info for durable reconnect
++ * @fp: ksmbd file pointer to store owner info
++ * @user: user pointer to copy from
++ *
++ * This function binds the current user's identity to the file handle
++ * to satisfy MS-SMB2 Step 8 (SecurityContext matching) during reconnect.
++ *
++ * Return: 0 on success, or negative error code on failure
++ */
++static int ksmbd_vfs_copy_durable_owner(struct ksmbd_file *fp,
++ struct ksmbd_user *user)
++{
++ if (!user)
++ return -EINVAL;
++
++ /* Duplicate the user name to ensure identity persistence */
++ fp->owner.name = kstrdup(user->name, GFP_KERNEL);
++ if (!fp->owner.name)
++ return -ENOMEM;
++
++ fp->owner.uid = user->uid;
++ fp->owner.gid = user->gid;
++
++ return 0;
++}
++
++/**
++ * ksmbd_vfs_compare_durable_owner - Verify if the requester is original owner
++ * @fp: existing ksmbd file pointer
++ * @user: user pointer of the reconnect requester
++ *
++ * Compares the UID, GID, and name of the current requester against the
++ * original owner stored in the file handle.
++ *
++ * Return: true if the user matches, false otherwise
++ */
++bool ksmbd_vfs_compare_durable_owner(struct ksmbd_file *fp,
++ struct ksmbd_user *user)
++{
++ if (!user || !fp->owner.name)
++ return false;
++
++ /* Check if the UID and GID match first (fast path) */
++ if (fp->owner.uid != user->uid || fp->owner.gid != user->gid)
++ return false;
++
++ /* Validate the account name to ensure the same SecurityContext */
++ if (strcmp(fp->owner.name, user->name))
++ return false;
++
++ return true;
++}
++
+ static bool session_fd_check(struct ksmbd_tree_connect *tcon,
+- struct ksmbd_file *fp)
++ struct ksmbd_file *fp, struct ksmbd_user *user)
+ {
+ struct ksmbd_inode *ci;
+ struct oplock_info *op;
+@@ -1002,6 +1062,9 @@ static bool session_fd_check(struct ksmb
+ if (!is_reconnectable(fp))
+ return false;
+
++ if (ksmbd_vfs_copy_durable_owner(fp, user))
++ return false;
++
+ conn = fp->conn;
+ ci = fp->f_ci;
+ down_write(&ci->m_lock);
+@@ -1033,7 +1096,7 @@ static bool session_fd_check(struct ksmb
+
+ void ksmbd_close_tree_conn_fds(struct ksmbd_work *work)
+ {
+- int num = __close_file_table_ids(&work->sess->file_table,
++ int num = __close_file_table_ids(work->sess,
+ work->tcon,
+ tree_conn_fd_check);
+
+@@ -1042,7 +1105,7 @@ void ksmbd_close_tree_conn_fds(struct ks
+
+ void ksmbd_close_session_fds(struct ksmbd_work *work)
+ {
+- int num = __close_file_table_ids(&work->sess->file_table,
++ int num = __close_file_table_ids(work->sess,
+ work->tcon,
+ session_fd_check);
+
+@@ -1140,6 +1203,10 @@ int ksmbd_reopen_durable_fd(struct ksmbd
+ }
+ up_write(&ci->m_lock);
+
++ fp->owner.uid = fp->owner.gid = 0;
++ kfree(fp->owner.name);
++ fp->owner.name = NULL;
++
+ return 0;
+ }
+
+@@ -1154,12 +1221,14 @@ int ksmbd_init_file_table(struct ksmbd_f
+ return 0;
+ }
+
+-void ksmbd_destroy_file_table(struct ksmbd_file_table *ft)
++void ksmbd_destroy_file_table(struct ksmbd_session *sess)
+ {
++ struct ksmbd_file_table *ft = &sess->file_table;
++
+ if (!ft->idr)
+ return;
+
+- __close_file_table_ids(ft, NULL, session_fd_check);
++ __close_file_table_ids(sess, NULL, session_fd_check);
+ idr_destroy(ft->idr);
+ kfree(ft->idr);
+ ft->idr = NULL;
+--- a/fs/smb/server/vfs_cache.h
++++ b/fs/smb/server/vfs_cache.h
+@@ -68,6 +68,13 @@ enum {
+ FP_CLOSED
+ };
+
++/* Owner information for durable handle reconnect */
++struct durable_owner {
++ unsigned int uid;
++ unsigned int gid;
++ char *name;
++};
++
+ struct ksmbd_file {
+ struct file *filp;
+ u64 persistent_id;
+@@ -114,6 +121,7 @@ struct ksmbd_file {
+ bool is_resilient;
+
+ bool is_posix_ctxt;
++ struct durable_owner owner;
+ };
+
+ static inline void set_ctx_actor(struct dir_context *ctx,
+@@ -140,7 +148,7 @@ static inline bool ksmbd_stream_fd(struc
+ }
+
+ int ksmbd_init_file_table(struct ksmbd_file_table *ft);
+-void ksmbd_destroy_file_table(struct ksmbd_file_table *ft);
++void ksmbd_destroy_file_table(struct ksmbd_session *sess);
+ int ksmbd_close_fd(struct ksmbd_work *work, u64 id);
+ struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, u64 id);
+ struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id);
+@@ -166,6 +174,8 @@ void ksmbd_free_global_file_table(void);
+ void ksmbd_set_fd_limit(unsigned long limit);
+ void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
+ unsigned int state);
++bool ksmbd_vfs_compare_durable_owner(struct ksmbd_file *fp,
++ struct ksmbd_user *user);
+
+ /*
+ * INODE hash
--- /dev/null
+From stable+bounces-239256-greg=kroah.com@vger.kernel.org Mon Apr 20 17:45:52 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Apr 2026 10:58:30 -0400
+Subject: scripts: generate_rust_analyzer.py: define scripts
+To: stable@vger.kernel.org
+Cc: Tamir Duberstein <tamird@kernel.org>, Daniel Almeida <daniel.almeida@collabora.com>, Fiona Behrens <me@kloenk.dev>, Trevor Gross <tmgross@umich.edu>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260420145830.1151150-1-sashal@kernel.org>
+
+From: Tamir Duberstein <tamird@kernel.org>
+
+[ Upstream commit 36c619f6bd793493294becb10a02fea370b67a91 ]
+
+Add IDE support for host-side scripts written in Rust. This support has
+been missing since these scripts were initially added in commit
+9a8ff24ce584 ("scripts: add `generate_rust_target.rs`"), thus add it.
+
+Change the existing instance of extension stripping to
+`pathlib.Path.stem` to maintain code consistency.
+
+Fixes: 9a8ff24ce584 ("scripts: add `generate_rust_target.rs`")
+Cc: stable@vger.kernel.org
+Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
+Reviewed-by: Fiona Behrens <me@kloenk.dev>
+Reviewed-by: Trevor Gross <tmgross@umich.edu>
+Link: https://patch.msgid.link/20260122-rust-analyzer-scripts-v1-1-ff6ba278170e@kernel.org
+Signed-off-by: Tamir Duberstein <tamird@kernel.org>
+[ changed `[std]` dep to `["std"]` and kept untyped `is_root_crate()` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/generate_rust_analyzer.py | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/scripts/generate_rust_analyzer.py
++++ b/scripts/generate_rust_analyzer.py
+@@ -188,6 +188,18 @@ def generate_crates(srctree, objtree, sy
+ append_crate_with_generated("uapi", ["core", "ffi", "pin_init"])
+ append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"])
+
++ scripts = srctree / "scripts"
++ makefile = (scripts / "Makefile").read_text()
++ for path in scripts.glob("*.rs"):
++ name = path.stem
++ if f"{name}-rust" not in makefile:
++ continue
++ append_crate(
++ name,
++ path,
++ ["std"],
++ )
++
+ def is_root_crate(build_file, target):
+ try:
+ contents = build_file.read_text()
+@@ -204,7 +216,7 @@ def generate_crates(srctree, objtree, sy
+ for folder in extra_dirs:
+ for path in folder.rglob("*.rs"):
+ logging.info("Checking %s", path)
+- name = path.name.replace(".rs", "")
++ name = path.stem
+
+ # Skip those that are not crate roots.
+ if not is_root_crate(path.parent / "Makefile", name) and \
crypto-authencesn-fix-src-offset-when-decrypting-in-place.patch
pwm-th1520-fix-clippy-1-warning.patch
drm-amdgpu-replace-pasid-idr-with-xarray.patch
+crypto-krb5enc-fix-sleepable-flag-handling-in-encrypt-dispatch.patch
+crypto-krb5enc-fix-async-decrypt-skipping-hash-verification.patch
+ksmbd-fix-use-after-free-in-__ksmbd_close_fd-via-durable-scavenger.patch
+ksmbd-validate-owner-of-durable-handle-on-reconnect.patch
+scripts-generate_rust_analyzer.py-define-scripts.patch