From: Greg Kroah-Hartman Date: Thu, 23 Apr 2026 08:57:40 +0000 (+0200) Subject: 6.18-stable patches X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=fa05af61dfcde48d17ee8b1c4ab76727d38fbbf1;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: crypto-krb5enc-fix-async-decrypt-skipping-hash-verification.patch crypto-krb5enc-fix-sleepable-flag-handling-in-encrypt-dispatch.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 --- diff --git a/queue-6.18/crypto-krb5enc-fix-async-decrypt-skipping-hash-verification.patch b/queue-6.18/crypto-krb5enc-fix-async-decrypt-skipping-hash-verification.patch new file mode 100644 index 0000000000..019d58457e --- /dev/null +++ b/queue-6.18/crypto-krb5enc-fix-async-decrypt-skipping-hash-verification.patch @@ -0,0 +1,159 @@ +From 3bfbf5f0a99c991769ec562721285df7ab69240b Mon Sep 17 00:00:00 2001 +From: Dudu Lu +Date: Mon, 20 Apr 2026 12:40:27 +0800 +Subject: crypto: krb5enc - fix async decrypt skipping hash verification + +From: Dudu Lu + +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 +Signed-off-by: Greg Kroah-Hartman + +Unset MAY_BACKLOG on the async completion path so the user won't +see back-to-back EINPROGRESS notifications. + +Signed-off-by: Herbert Xu +--- + 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) diff --git a/queue-6.18/crypto-krb5enc-fix-sleepable-flag-handling-in-encrypt-dispatch.patch b/queue-6.18/crypto-krb5enc-fix-sleepable-flag-handling-in-encrypt-dispatch.patch new file mode 100644 index 0000000000..9cbab0da3c --- /dev/null +++ b/queue-6.18/crypto-krb5enc-fix-sleepable-flag-handling-in-encrypt-dispatch.patch @@ -0,0 +1,52 @@ +From 2ef3bac16fb5e9eee4fb1d722578a79b751ea58a Mon Sep 17 00:00:00 2001 +From: Wesley Atwell +Date: Mon, 9 Mar 2026 00:26:24 -0600 +Subject: crypto: krb5enc - fix sleepable flag handling in encrypt dispatch + +From: Wesley Atwell + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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); + } diff --git a/queue-6.18/ksmbd-fix-use-after-free-in-__ksmbd_close_fd-via-durable-scavenger.patch b/queue-6.18/ksmbd-fix-use-after-free-in-__ksmbd_close_fd-via-durable-scavenger.patch new file mode 100644 index 0000000000..a9d003e716 --- /dev/null +++ b/queue-6.18/ksmbd-fix-use-after-free-in-__ksmbd_close_fd-via-durable-scavenger.patch @@ -0,0 +1,137 @@ +From stable+bounces-239948-greg=kroah.com@vger.kernel.org Mon Apr 20 20:11:45 2026 +From: Sasha Levin +Date: Mon, 20 Apr 2026 12:38:53 -0400 +Subject: ksmbd: fix use-after-free in __ksmbd_close_fd() via durable scavenger +To: stable@vger.kernel.org +Cc: Namjae Jeon , munan Huang , ChenXiaoSong , Steve French , Sasha Levin +Message-ID: <20260420163854.1302592-1-sashal@kernel.org> + +From: Namjae Jeon + +[ 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 +Signed-off-by: munan Huang +Reviewed-by: ChenXiaoSong +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Stable-dep-of: 49110a8ce654 ("ksmbd: validate owner of durable handle on reconnect") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -370,9 +370,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); +@@ -902,6 +904,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; +@@ -918,6 +921,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; +@@ -996,6 +1005,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); +@@ -1007,9 +1019,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) { +@@ -1020,13 +1046,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; + } + diff --git a/queue-6.18/ksmbd-validate-owner-of-durable-handle-on-reconnect.patch b/queue-6.18/ksmbd-validate-owner-of-durable-handle-on-reconnect.patch new file mode 100644 index 0000000000..3aea09c852 --- /dev/null +++ b/queue-6.18/ksmbd-validate-owner-of-durable-handle-on-reconnect.patch @@ -0,0 +1,326 @@ +From stable+bounces-239949-greg=kroah.com@vger.kernel.org Mon Apr 20 19:10:17 2026 +From: Sasha Levin +Date: Mon, 20 Apr 2026 12:38:54 -0400 +Subject: ksmbd: validate owner of durable handle on reconnect +To: stable@vger.kernel.org +Cc: Namjae Jeon , Davide Ornaghi , Navaneeth K , Steve French , Sasha Levin +Message-ID: <20260420163854.1302592-2-sashal@kernel.org> + +From: Namjae Jeon + +[ 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 +Reported-by: Navaneeth K +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/mgmt/user_session.c | 7 +-- + 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(+), 15 deletions(-) + +--- a/fs/smb/server/mgmt/user_session.c ++++ b/fs/smb/server/mgmt/user_session.c +@@ -161,11 +161,10 @@ void ksmbd_session_destroy(struct ksmbd_ + if (!sess) + return; + ++ 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); +@@ -396,7 +395,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 +@@ -3022,7 +3022,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 +@@ -18,6 +18,7 @@ + #include "connection.h" + #include "mgmt/tree_connect.h" + #include "mgmt/user_session.h" ++#include "mgmt/user_config.h" + #include "smb_common.h" + #include "server.h" + +@@ -383,6 +384,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); + } + +@@ -694,11 +697,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; +@@ -711,7 +716,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); +@@ -763,7 +768,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; + } +@@ -898,8 +904,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; +@@ -909,6 +969,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); +@@ -940,7 +1003,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); + +@@ -949,7 +1012,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); + +@@ -1046,6 +1109,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; + } + +@@ -1060,12 +1127,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 diff --git a/queue-6.18/scripts-generate_rust_analyzer.py-define-scripts.patch b/queue-6.18/scripts-generate_rust_analyzer.py-define-scripts.patch new file mode 100644 index 0000000000..8ec0d6a352 --- /dev/null +++ b/queue-6.18/scripts-generate_rust_analyzer.py-define-scripts.patch @@ -0,0 +1,63 @@ +From stable+bounces-239763-greg=kroah.com@vger.kernel.org Mon Apr 20 18:08:09 2026 +From: Sasha Levin +Date: Mon, 20 Apr 2026 12:05:50 -0400 +Subject: scripts: generate_rust_analyzer.py: define scripts +To: stable@vger.kernel.org +Cc: Tamir Duberstein , Daniel Almeida , Fiona Behrens , Trevor Gross , Sasha Levin +Message-ID: <20260420160550.1184938-1-sashal@kernel.org> + +From: Tamir Duberstein + +[ 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 +Reviewed-by: Fiona Behrens +Reviewed-by: Trevor Gross +Link: https://patch.msgid.link/20260122-rust-analyzer-scripts-v1-1-ff6ba278170e@kernel.org +Signed-off-by: Tamir Duberstein +[ changed `[std]` dep to `["std"]` and kept untyped `is_root_crate()` ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -166,6 +166,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() +@@ -182,7 +194,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 \ diff --git a/queue-6.18/series b/queue-6.18/series index cd1b953d65..0b6a08e962 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -8,3 +8,8 @@ arm64-errata-work-around-early-cme-dvmsync-acknowled.patch ipv6-add-null-checks-for-idev-in-srv6-paths.patch net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.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 +scripts-generate_rust_analyzer.py-define-scripts.patch +ksmbd-fix-use-after-free-in-__ksmbd_close_fd-via-durable-scavenger.patch +ksmbd-validate-owner-of-durable-handle-on-reconnect.patch