mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
tty: Avoid leaving dangling pointers in tty_drop_ctty()
The TIOCNOTTY handler detaches the calling process from its controlling
terminal. It clears the link from the session to the tty, but not the
pointers from the tty to the session and process group. This means that
sess_release() doesn't call tty_rel_sess(), and that pgdelete() doesn't
call tty_rel_pgrp(), so the pointers are left dangling.
Fix this by clearing pointers in tty_drop_ctty(). Add a standalone
regression test.
Approved by: so
Security: FreeBSD-SA-26:10.tty
Security: CVE-2026-5398
Reported by: Nicholas Carlini <npc@anthropic.com>
Reviewed by: kib, kevans
Fixes: 1b50b999f9 ("tty: implement TIOCNOTTY")
Differential Revision: https://reviews.freebsd.org/D56046
This commit is contained in:
parent
6ffe3a31b8
commit
e1ed334011
3 changed files with 87 additions and 0 deletions
|
|
@ -1262,6 +1262,10 @@ tty_drop_ctty(struct tty *tp, struct proc *p)
|
|||
session->s_ttydp = NULL;
|
||||
SESS_UNLOCK(session);
|
||||
|
||||
if (tp->t_session == session) {
|
||||
tp->t_session = NULL;
|
||||
tp->t_pgrp = NULL;
|
||||
}
|
||||
tp->t_sessioncnt--;
|
||||
p->p_flag &= ~P_CONTROLT;
|
||||
PROC_UNLOCK(p);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ ATF_TESTS_C+= subr_physmem_test
|
|||
PLAIN_TESTS_C+= subr_unit_test
|
||||
ATF_TESTS_C+= sysctl_kern_proc
|
||||
ATF_TESTS_C+= sys_getrandom
|
||||
PLAIN_TESTS_C+= tiocnotty
|
||||
ATF_TESTS_C+= tty_pts
|
||||
ATF_TESTS_C+= unix_dgram
|
||||
ATF_TESTS_C+= unix_passfd_dgram
|
||||
|
|
|
|||
82
tests/sys/kern/tiocnotty.c
Normal file
82
tests/sys/kern/tiocnotty.c
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Mark Johnston <markj@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* A regression test that exercises a bug where TIOCNOTTY would leave some
|
||||
* dangling pointers behind in the controlling terminal structure.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int master, slave, status;
|
||||
pid_t child;
|
||||
|
||||
master = posix_openpt(O_RDWR | O_NOCTTY);
|
||||
if (master < 0)
|
||||
err(1, "posix_openpt");
|
||||
if (grantpt(master) < 0)
|
||||
err(1, "grantpt");
|
||||
if (unlockpt(master) < 0)
|
||||
err(1, "unlockpt");
|
||||
|
||||
child = fork();
|
||||
if (child < 0)
|
||||
err(1, "fork");
|
||||
if (child == 0) {
|
||||
if (setsid() < 0)
|
||||
err(1, "setsid");
|
||||
slave = open(ptsname(master), O_RDWR | O_NOCTTY);
|
||||
if (slave < 0)
|
||||
err(2, "open");
|
||||
if (ioctl(slave, TIOCSCTTY, 0) < 0)
|
||||
err(3, "ioctl(TIOCSCTTY)");
|
||||
/* Detach ourselves from the controlling terminal. */
|
||||
if (ioctl(slave, TIOCNOTTY, 0) < 0)
|
||||
err(4, "ioctl(TIOCNOTTY)");
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
if (waitpid(child, &status, 0) < 0)
|
||||
err(1, "waitpid");
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
|
||||
errx(1, "child exited with status %d", WEXITSTATUS(status));
|
||||
|
||||
child = fork();
|
||||
if (child < 0)
|
||||
err(1, "fork");
|
||||
if (child == 0) {
|
||||
struct winsize winsz;
|
||||
|
||||
if (setsid() < 0)
|
||||
err(1, "setsid");
|
||||
slave = open(ptsname(master), O_RDWR | O_NOCTTY);
|
||||
if (slave < 0)
|
||||
err(2, "open");
|
||||
/* Dereferences dangling t_pgrp pointer in the terminal. */
|
||||
memset(&winsz, 0xff, sizeof(winsz));
|
||||
if (ioctl(slave, TIOCSWINSZ, &winsz) < 0)
|
||||
err(3, "ioctl(TIOCSWINSZ)");
|
||||
/* Dereferences dangling t_session pointer in the terminal. */
|
||||
if (ioctl(slave, TIOCSCTTY, 0) < 0)
|
||||
err(4, "ioctl(TIOCSCTTY)");
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
if (waitpid(child, &status, 0) < 0)
|
||||
err(1, "waitpid");
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
|
||||
errx(1, "child exited with status %d", WEXITSTATUS(status));
|
||||
}
|
||||
Loading…
Reference in a new issue