Unverified Commit 7a3d112c authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!3607 Fix CVE-2023-6546

Merge Pull Request from: @ci-robot 
 
PR sync from: Yi Yang <yiyang13@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/BXYBX4V55RK3AAJKEA5CE3XTGUKHL7UB/ 
Fix CVE-2023-6546

Daniel Starke (1):
  tty: n_gsm: fix restart handling via CLD command

Yi Yang (1):
  tty: n_gsm: fix the UAF caused by race condition in gsm_cleanup_mux


-- 
2.25.1
 
https://gitee.com/src-openeuler/kernel/issues/I8QFUO 
 
Link:https://gitee.com/openeuler/kernel/pulls/3607

 

Reviewed-by: default avatarLu Jialin <lujialin4@huawei.com>
Reviewed-by: default avatarLiu YongQiang <liuyongqiang13@huawei.com>
Signed-off-by: default avatarZhang Changzhong <zhangchangzhong@huawei.com>
parents 6b9208d8 d354c17d
Loading
Loading
Loading
Loading
+22 −49
Original line number Original line Diff line number Diff line
@@ -2024,49 +2024,36 @@ static void gsm_error(struct gsm_mux *gsm,
	gsm->io_error++;
	gsm->io_error++;
}
}


static int gsm_disconnect(struct gsm_mux *gsm)
{
	struct gsm_dlci *dlci = gsm->dlci[0];
	struct gsm_control *gc;

	if (!dlci)
		return 0;

	/* In theory disconnecting DLCI 0 is sufficient but for some
	   modems this is apparently not the case. */
	gc = gsm_control_send(gsm, CMD_CLD, NULL, 0);
	if (gc)
		gsm_control_wait(gsm, gc);

	del_timer_sync(&gsm->t2_timer);
	/* Now we are sure T2 has stopped */

	gsm_dlci_begin_close(dlci);
	wait_event_interruptible(gsm->event,
				dlci->state == DLCI_CLOSED);

	if (signal_pending(current))
		return -EINTR;

	return 0;
}

/**
/**
 *	gsm_cleanup_mux		-	generic GSM protocol cleanup
 *	gsm_cleanup_mux		-	generic GSM protocol cleanup
 *	@gsm: our mux
 *	@gsm: our mux
 *	@disc: disconnect link?
 *
 *
 *	Clean up the bits of the mux which are the same for all framing
 *	Clean up the bits of the mux which are the same for all framing
 *	protocols. Remove the mux from the mux table, stop all the timers
 *	protocols. Remove the mux from the mux table, stop all the timers
 *	and then shut down each device hanging up the channels as we go.
 *	and then shut down each device hanging up the channels as we go.
 */
 */


static void gsm_cleanup_mux(struct gsm_mux *gsm)
static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
{
{
	int i;
	int i;
	struct gsm_dlci *dlci = gsm->dlci[0];
	struct gsm_dlci *dlci;
	struct gsm_msg *txq, *ntxq;
	struct gsm_msg *txq, *ntxq;


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

	dlci = gsm->dlci[0];
	if (dlci) {
		if (disc && dlci->state != DLCI_CLOSED) {
			gsm_dlci_begin_close(dlci);
			wait_event(gsm->event, dlci->state == DLCI_CLOSED);
		}
		dlci->dead = true;
	}

	/* Finish outstanding timers, making sure they are done */
	del_timer_sync(&gsm->t2_timer);


	spin_lock(&gsm_mux_lock);
	spin_lock(&gsm_mux_lock);
	for (i = 0; i < MAX_MUX; i++) {
	for (i = 0; i < MAX_MUX; i++) {
@@ -2080,13 +2067,7 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)
	if (i == MAX_MUX)
	if (i == MAX_MUX)
		return;
		return;


	del_timer_sync(&gsm->t2_timer);
	/* Now we are sure T2 has stopped */
	if (dlci)
		dlci->dead = 1;

	/* Free up any link layer users */
	/* Free up any link layer users */
	mutex_lock(&gsm->mutex);
	for (i = 0; i < NUM_DLCI; i++)
	for (i = 0; i < NUM_DLCI; i++)
		if (gsm->dlci[i])
		if (gsm->dlci[i])
			gsm_dlci_release(gsm->dlci[i]);
			gsm_dlci_release(gsm->dlci[i]);
@@ -2285,7 +2266,7 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
	WARN_ON(tty != gsm->tty);
	WARN_ON(tty != gsm->tty);
	for (i = 1; i < NUM_DLCI; i++)
	for (i = 1; i < NUM_DLCI; i++)
		tty_unregister_device(gsm_tty_driver, base + i);
		tty_unregister_device(gsm_tty_driver, base + i);
	gsm_cleanup_mux(gsm);
	gsm_cleanup_mux(gsm, false);
	tty_kref_put(gsm->tty);
	tty_kref_put(gsm->tty);
	gsm->tty = NULL;
	gsm->tty = NULL;
}
}
@@ -2391,7 +2372,7 @@ static int gsmld_open(struct tty_struct *tty)


	ret = gsmld_attach_gsm(tty, gsm);
	ret = gsmld_attach_gsm(tty, gsm);
	if (ret != 0) {
	if (ret != 0) {
		gsm_cleanup_mux(gsm);
		gsm_cleanup_mux(gsm, false);
		mux_put(gsm);
		mux_put(gsm);
	}
	}
	return ret;
	return ret;
@@ -2540,19 +2521,11 @@ static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm,


	/*
	/*
	 *	Close down what is needed, restart and initiate the new
	 *	Close down what is needed, restart and initiate the new
	 *	configuration
	 *	configuration. On the first time there is no DLCI[0]
	 *	and closing or cleaning up is not necessary.
	 */
	 */

	if (need_close || need_restart)
	if (need_close || need_restart) {
		gsm_cleanup_mux(gsm, true);
		int ret;

		ret = gsm_disconnect(gsm);

		if (ret)
			return ret;
	}
	if (need_restart)
		gsm_cleanup_mux(gsm);


	gsm->initiator = c->initiator;
	gsm->initiator = c->initiator;
	gsm->mru = c->mru;
	gsm->mru = c->mru;