Contributed by nayden on from the moar ptys dept.
The second report from the just completed t2k17 hackathon comes from Ted Unangst (tedu@), who writes:
I did a bit of this and that, but the project that probably has the most interesting explanation has to do with pseudo terminals. This has a bit of history behind it that goes back to the early days of unix.
Way back when, terminals were really teletypes, which is why the terminal driver is called tty. Users would connect to a unix system via electronic typewriters connected to serial ports. Some time later the typewriters turned into terminals, like the VT100, still connected to serial ports. Or maybe users dialed into the server using a modem. The idea of a user session became strongly attached to the terminal concept.
Then came networking and xterms and terminals where the end point wasn't a hardware device. And so we got the pseudo terminal, the pty, where both sides of the terminal were just software running on the same system. Not limited by physical hardware constraints like how many ports fit in a case, it's possible to have many many many pseudo terminals on a running system.
This leads to a problem. What do we name them all? Also, how do sshd and tmux know which pty to use? In the olden days, you'd just walk through /dev and try a bunch of names iteratively until you find one you liked. This is kind of messy, and prone to lots of race conditions and security holes.
The solution is a function called openpty. Internally, this opens /dev/ptm and does a magic ioctl to allocate a free pty. Userland doesn't need to worry about naming or iterating or anything like that. Well, userland applications don't; but libc still has some work to do.
The ptm ioctl only finds a free name and returns that. The openpty implementation is still responsible for opening the device nodes in /dev. If they don't exist, it will fail. By default, OpenBSD ships with 62 pty nodes in /dev, ptyp*. The kernel supports several more by chewing through additional letters of the alphabet, ptyr*, ptyq*, etc. But first you must remember to run MAKEDEV. And even if you run MAKEDEV, there's still a hard limit of 992 because eventually the naming scheme runs out of letters entirely.
With the history out of the way, I decided (read: was strongly hinted at by Henning) that 992 is kind of a low limit. It seems like a lot, but stick a few hundred users on a box, some tmux sessions, some authpf, and it goes by quick. Adding more ptys requires a change to the naming scheme, which is inconvenient because nobody will have the required nodes, meaning a change to MAKEDEV and so forth.
So the first thing to do is really to fix the ptm ioctl so that it will create new pty nodes on the fly as necessary. Then libc will find them and use them, without requiring the sysadmin to manually intervene. I got most of the code for that done. It requires a bit of style refinement and further review, and then once that's in we can start thinking about how to expand beyond 992 possible names.
Thanks for the report and work, Ted!
(Comments are closed)