From: Fredric Cover <fredric.cover.lkernel@gmail.com> mainline inclusion from mainline-v7.3-rc3 commit 42d3358bf145f27d32350037e67d3527e9098c1e 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... -------------------------------- In copy_ref_data(), struct cache_entry *ce has its fields populated at the beginning of the function. Later, if alloc_target fails with an ERR_PTR, free_tgts() is called on the cache, leaving the cache metadata populated without any targets. Critically, this extends ce->etime, making the cache appear valid for longer without any targets. Also, free_tgts() does not set ce->numtgts to zero. On error, when the cache is freed, ce->numtgts is not zeroed, and other cache users may attempt to access nonexistent entries. Update fields after copying targets to prevent partial-state updates. Set ce->numtgts to zero at the end of free_tgts(). Signed-off-by: Fredric Cover <fredric.cover.lkernel@gmail.com> Signed-off-by: Paulo Alcantara <pc@manguebit.org> Conflicts: fs/cifs/dfs_cache.c fs/smb/client/dfs_cache.c [Context differences.] Signed-off-by: Yifan Qiao <qiaoyifan4@huawei.com> --- fs/cifs/dfs_cache.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c index 01e82cb516bb..b2b6ab803c75 100644 --- a/fs/cifs/dfs_cache.c +++ b/fs/cifs/dfs_cache.c @@ -119,6 +119,7 @@ static inline void free_tgts(struct cache_entry *ce) kfree(t); } + ce->numtgts = 0; WRITE_ONCE(ce->tgthint, NULL); } @@ -379,12 +380,6 @@ static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs, { int i; - ce->ttl = refs[0].ttl; - ce->etime = get_expire_time(ce->ttl); - ce->srvtype = refs[0].server_type; - ce->flags = refs[0].ref_flag; - ce->path_consumed = refs[0].path_consumed; - for (i = 0; i < numrefs; i++) { struct cache_dfs_tgt *t; @@ -399,12 +394,18 @@ static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs, } else { list_add_tail(&t->list, &ce->tlist); } - ce->numtgts++; } ce->tgthint = list_first_entry_or_null(&ce->tlist, struct cache_dfs_tgt, list); + ce->ttl = refs[0].ttl; + ce->etime = get_expire_time(ce->ttl); + ce->srvtype = refs[0].server_type; + ce->flags = refs[0].ref_flag; + ce->path_consumed = refs[0].path_consumed; + ce->numtgts = numrefs; + return 0; } @@ -648,7 +649,6 @@ static int __update_cache_entry(const char *path, } free_tgts(ce); - ce->numtgts = 0; rc = copy_ref_data(refs, numrefs, ce, th); -- 2.52.0