mirror of
https://github.com/torvalds/linux.git
synced 2026-10-08 11:36:02 +02:00
smb: client: harden DFS cache against invalid target hints
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>
This commit is contained in:
parent
b8e5dc4f95
commit
bf86c08123
|
|
@ -869,13 +869,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:
|
||||
|
|
@ -915,10 +924,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);
|
||||
|
||||
|
|
@ -959,7 +975,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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user