Commit e1591d50 authored by Yi Yang's avatar Yi Yang
Browse files

tty: n_gsm: fix the UAF caused by race condition in gsm_cleanup_mux

mainline inclusion
from mainline-v6.5-rc7
commit 3c4f8333
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8QFUO
CVE: CVE-2023-6546

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3c4f8333b582487a2d1e02171f1465531cde53e3

--------------------------------

In commit 9b9c8195 ("tty: n_gsm: fix UAF in gsm_cleanup_mux"), the UAF
problem is not completely fixed. There is a race condition in
gsm_cleanup_mux(), which caused this UAF.

The UAF problem is triggered by the following race:
task[5046]                     task[5054]
-----------------------        -----------------------
gsm_cleanup_mux();
dlci = gsm->dlci[0];
mutex_lock(&gsm->mutex);
                               gsm_cleanup_mux();
			       dlci = gsm->dlci[0]; //Didn't take the lock
gsm_dlci_release(gsm->dlci[i]);
gsm->dlci[i] = NULL;
mutex_unlock(&gsm->mutex);
                               mutex_lock(&gsm->mutex);
			       dlci->dead = true; //UAF

Fix it by assigning values after mutex_lock().

Link: https://syzkaller.appspot.com/text?tag=CrashReport&x=176188b5a80000


Cc: stable <stable@kernel.org>
Fixes: 9b9c8195 ("tty: n_gsm: fix UAF in gsm_cleanup_mux")
Fixes: aa371e96 ("tty: n_gsm: fix restart handling via CLD command")
Signed-off-by: default avatarYi Yang <yiyang13@huawei.com>
Co-developed-by: default avatarQiumiao Zhang <zhangqiumiao1@huawei.com>
Signed-off-by: default avatarQiumiao Zhang <zhangqiumiao1@huawei.com>
Link: https://lore.kernel.org/r/20230811031121.153237-1-yiyang13@huawei.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarYi Yang <yiyang13@huawei.com>
parent 2670bf30
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -2159,12 +2159,13 @@ static void gsm_error(struct gsm_mux *gsm,
static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
{
	int i;
	struct gsm_dlci *dlci = gsm->dlci[0];
	struct gsm_dlci *dlci;
	struct gsm_msg *txq, *ntxq;

	gsm->dead = true;
	mutex_lock(&gsm->mutex);

	dlci = gsm->dlci[0];
	if (dlci) {
		if (disc && dlci->state != DLCI_CLOSED) {
			gsm_dlci_begin_close(dlci);