From 4baaec48fed84ee71f8643d90fa0aaa9fb1ae276 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Mon, 22 Apr 2024 03:39:50 +0000 Subject: [PATCH] specfs: Fix serialization of dodgy pgrp/session release logic. XXX not sure if this is right --- sys/miscfs/specfs/spec_vnops.c | 72 +++++++++++++++++----------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c index 47dcc0869aa7..9dd2406726be 100644 --- a/sys/miscfs/specfs/spec_vnops.c +++ b/sys/miscfs/specfs/spec_vnops.c @@ -1588,7 +1588,7 @@ spec_close(void *v) struct session *sess; dev_t dev; int flags = ap->a_fflag; - int mode, error, count; + int mode, error, vcount, count; specnode_t *sn; specdev_t *sd; @@ -1609,39 +1609,6 @@ spec_close(void *v) switch (vp->v_type) { case VCHR: - /* - * Hack: a tty device that is a controlling terminal - * has a reference from the session structure. We - * cannot easily tell that a character device is a - * controlling terminal, unless it is the closing - * process' controlling terminal. In that case, if the - * open count is 1 release the reference from the - * session. Also, remove the link from the tty back to - * the session and pgrp. - * - * XXX V. fishy. - */ - mutex_enter(&proc_lock); - sess = curlwp->l_proc->p_session; - if (sn->sn_opencnt == 1 && vp == sess->s_ttyvp) { - mutex_spin_enter(&tty_lock); - sess->s_ttyvp = NULL; - if (sess->s_ttyp->t_session != NULL) { - sess->s_ttyp->t_pgrp = NULL; - sess->s_ttyp->t_session = NULL; - mutex_spin_exit(&tty_lock); - /* Releases proc_lock. */ - proc_sessrele(sess); - } else { - mutex_spin_exit(&tty_lock); - if (sess->s_ttyp->t_pgrp != NULL) - panic("spec_close: spurious pgrp ref"); - mutex_exit(&proc_lock); - } - vrele(vp); - } else - mutex_exit(&proc_lock); - /* * If the vnode is locked, then we are in the midst * of forcably closing the device, otherwise we only @@ -1707,7 +1674,7 @@ spec_close(void *v) KASSERTMSG(sn->sn_opencnt <= sd->sd_opencnt, "sn_opencnt=%u > sd_opencnt=%u", sn->sn_opencnt, sd->sd_opencnt); - sn->sn_opencnt--; + vcount = --sn->sn_opencnt; count = --sd->sd_opencnt; if (vp->v_type == VBLK) { KASSERTMSG(count == 0, "block device with %u opens", @@ -1723,6 +1690,41 @@ spec_close(void *v) } mutex_exit(&device_lock); + if (vp->v_type == VCHR && vcount == 0) { + /* + * Hack: a tty device that is a controlling terminal + * has a reference from the session structure. We + * cannot easily tell that a character device is a + * controlling terminal, unless it is the closing + * process' controlling terminal. In that case, if the + * open count is 1 release the reference from the + * session. Also, remove the link from the tty back to + * the session and pgrp. + * + * XXX V. fishy. + */ + mutex_enter(&proc_lock); + sess = curlwp->l_proc->p_session; + if (vp == sess->s_ttyvp) { + mutex_spin_enter(&tty_lock); + sess->s_ttyvp = NULL; + if (sess->s_ttyp->t_session != NULL) { + sess->s_ttyp->t_pgrp = NULL; + sess->s_ttyp->t_session = NULL; + mutex_spin_exit(&tty_lock); + /* Releases proc_lock. */ + proc_sessrele(sess); + } else { + mutex_spin_exit(&tty_lock); + if (sess->s_ttyp->t_pgrp != NULL) + panic("spec_close: spurious pgrp ref"); + mutex_exit(&proc_lock); + } + vrele(vp); + } else + mutex_exit(&proc_lock); + } + if (count != 0) return 0;