Controlling Terminal Acquisition
On Linux, a daemon that accidentally opens a terminal device can accidentally make that terminal its controlling terminal.
Controlling terminals have a lot of power. Specifically, they can send signals to that daemon going forward and also interrupt the processes’ execution. If an attacker can predict and write one of the file paths opened by a daemon, if that daemon does not pass the special O_NOCTTY flag, then they can create a pseudoterminal that they control and possibly make the daemon attach to it, putting themselves in the position of sending signals to that daemon.
This is described in more detail in daemon(7), where it is listed as the last item to look for when implementing a daemon:
As new-style daemons are invoked without a controlling TTY (but as their own session leaders) care should be taken to always specify
O_NOCTTYon open(2) calls that possibly reference a TTY device node, so that no controlling TTY is accidentally acquired.
What is the portable way to purposefully acquire a controlling terminal?
First open(2) the terminal device, then call the TIOCSCTTY IOCTL to make it the controlling terminal.
This is a (correct) snippet from the foot terminal source code, file slave.c:
pts = open(pts_name, O_RDWR);
if (pts == -1) {
LOG_ERRNO("failed to open pseudo terminal slave device");
goto err;
}
if (ioctl(pts, TIOCSCTTY, 0) < 0) {
LOG_ERRNO("failed to configure controlling terminal");
goto err;
}
What happens on other Operating Systems?
Other UNIX-like operating systems have largely addressed the issue – open(2) does not implicitly attach to a controlling terminal any more, and attachment must be done explicitly with the IOCTL.
💡 Software which has been ported to run on the BSDs is already doing it correctly.
The BSDs require the IOCTL for attachment
According to AdvancedProgrammingInTheUnixEnvironment (3rd edition), section 9.6, the split was initially between BSD-based systems (which only attach with the IOCTL) and System V-based systems (which attach implicitly on open(2)).
For the three main BSD derivatives, the man page termios(4) (FreeBSD, OpenBSD, NetBSD) has the same wording:
A controlling terminal is never acquired by merely opening a terminal device file.
Mac OS attaches implicitly on open(2)
According to AdvancedProgrammingInTheUnixEnvironment, on Mac OS, an open(2) on a terminal does the attachment implicitly.