From: Fredric Cover <fredric.cover.lkernel@gmail.com> mainline inclusion from mainline-v7.3-rc1 commit bf86c08123c6ab8c61cc0be1dad7540db93738ff category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18921 CVE: CVE-2026-89636 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Currently, get_tgt_name() returns ERR_PTR(-ENOENT) when ce->tgthint is NULL, and dfs_cache_noreq_update_tgthint() assumes ce->tgthint is always valid. In preparation for clearing ce->tgthint in free_tgts(), harden callers of get_tgt_name() against ERR_PTR results and harden dfs_cache_noreq_update_tgthint() against NULL pointer dereferences. Cc: stable@vger.kernel.org Signed-off-by: Fredric Cover <fredric.cover.lkernel@gmail.com> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org> Signed-off-by: Yifan Qiao <qiaoyifan4@huawei.com> --- fs/smb/client/dfs_cache.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/fs/smb/client/dfs_cache.c b/fs/smb/client/dfs_cache.c index 433f546055b9..0b7bad920a8c 100644 --- a/fs/smb/client/dfs_cache.c +++ b/fs/smb/client/dfs_cache.c @@ -871,13 +871,22 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nl goto out_free_path; } - if (ref) - rc = setup_referral(path, ce, ref, get_tgt_name(ce)); - else + if (ref) { + char *target = get_tgt_name(ce); + + if (IS_ERR(target)) { + rc = PTR_ERR(target); + goto out_unlock; + } + rc = setup_referral(path, ce, ref, target); + } else { rc = 0; + } + if (!rc && tgt_list) rc = get_targets(ce, tgt_list); +out_unlock: up_read(&htable_rw_lock); out_free_path: @@ -917,10 +926,17 @@ int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref, goto out_unlock; } - if (ref) - rc = setup_referral(path, ce, ref, get_tgt_name(ce)); - else + if (ref) { + char *target = get_tgt_name(ce); + + if (IS_ERR(target)) { + rc = PTR_ERR(target); + goto out_unlock; + } + rc = setup_referral(path, ce, ref, target); + } else { rc = 0; + } if (!rc && tgt_list) rc = get_targets(ce, tgt_list); @@ -961,7 +977,8 @@ void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt t = READ_ONCE(ce->tgthint); - if (unlikely(!strcasecmp(it->it_name, t->name))) + /* Check 't' in case ce->tgthint was cleared by free_tgts() */ + if (t && unlikely(!strcasecmp(it->it_name, t->name))) goto out_unlock; list_for_each_entry(t, &ce->tlist, list) { -- 2.52.0