From: Zicheng Qu <quzicheng@huawei.com> hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/10133 ------------------------ vstream_get_by_user_stream_id() stores the matched vstream in a static local variable that is never reset. When no entry matches the requested user_stream_id, the function returns the value left over from a previous call instead of NULL. If that vstream has been freed in the meantime, logic_cq_alloc() receives a dangling pointer and dereferences it (vstream->xcu and vstream->logic_vcq_id), producing a use-after-free that can be triggered from userspace via the vstream_manage syscall. Track whether the lookup matched in a local flag and return NULL when it did not, so that no stale pointer can escape the lookup. Fixes: 8dde1f2e6bf6 ("xsched: Introduce vstream management") Signed-off-by: Zicheng Qu <quzicheng@huawei.com> Signed-off-by: Tang Hui <tanghui20@huawei.com> --- kernel/xsched/vstream.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/kernel/xsched/vstream.c b/kernel/xsched/vstream.c index 074d030b14f1f..e7574236b363e 100644 --- a/kernel/xsched/vstream.c +++ b/kernel/xsched/vstream.c @@ -366,17 +366,23 @@ vstream_get_by_user_stream_id(struct xsched_cu *xcu, uint32_t user_stream_id) { int id; static vstream_info_t *ret; + int ret_valid = 0; mutex_lock(&xcu->vs_array_lock); for (id = 0; id < MAX_VSTREAM_NUM; id++) { if (xcu->vs_array[id] != NULL && xcu->vs_array[id]->id == user_stream_id) { ret = xcu->vs_array[id]; + ret_valid = 1; break; } } mutex_unlock(&xcu->vs_array_lock); - return ret; + + if (ret_valid) + return ret; + else + return NULL; } static int vstream_bind_to_xcu(vstream_info_t *vstream_info) @@ -507,8 +513,13 @@ static int logic_cq_alloc(struct vstream_args *arg) vstream = vstream_get_by_user_stream_id(xcu_found, logic_cq_alloc_para->user_stream_id); - if (vstream) - xcu_found = vstream->xcu; + + if (!vstream) { + XSCHED_ERR("Invalid stream id.\n"); + return -EINVAL; + } + + xcu_found = vstream->xcu; params.group = xcu_found->group; params.fd = arg->fd; params.payload = arg->payload; @@ -518,8 +529,7 @@ static int logic_cq_alloc(struct vstream_args *arg) XSCHED_ERR("Fail to alloc logic CQ memory to a vstream.\n"); return err; } - if (vstream) - vstream->logic_vcq_id = logic_cq_id; + vstream->logic_vcq_id = logic_cq_id; return 0; } -- 2.34.1