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 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/kernel/xsched/vstream.c b/kernel/xsched/vstream.c index 074d030b14f1f..49bb28e02c0ba 100644 --- a/kernel/xsched/vstream.c +++ b/kernel/xsched/vstream.c @@ -365,7 +365,7 @@ static vstream_info_t * vstream_get_by_user_stream_id(struct xsched_cu *xcu, uint32_t user_stream_id) { int id; - static vstream_info_t *ret; + vstream_info_t *ret = NULL; mutex_lock(&xcu->vs_array_lock); for (id = 0; id < MAX_VSTREAM_NUM; id++) { @@ -376,6 +376,7 @@ vstream_get_by_user_stream_id(struct xsched_cu *xcu, uint32_t user_stream_id) } } mutex_unlock(&xcu->vs_array_lock); + return ret; } @@ -507,8 +508,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 +524,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