Thanks to the comment by @mikeserv I've found out how to revive it.
I have only tested this on Linux 4.0.7, so for much earlier or much later versions it may not work.
mount /dev/pts -o remount,gid=5,mode=620
devpts filesystem in a
chroot without using the
newinstance option caused it to mount the same "instance" of
/dev/pts, containing the same ptys. Passing no
gid argument, according to the man page, causes new ptys to be created with the same gid as the process that spawned it. Apparently this (lack of) mount option affects the entire
devpts instance, so the original
/dev/pts is no longer reassigning ptys to the
tty group. I still don't know why urxvt needs its ptys to be in that group while xterm doesn't.
Some more notes on this:
- It seems normal that
/dev/pts/ptmx has mode 000 (root:root) while
/dev/ptmx has mode 666 (root:tty). They do however point to the same block device, so setting
ptmxmode seems unnecessary but harmless.
- The default
mode (600) seems to work, but the tty gets created with mode 620 anyway. Something might be changing its mode. When my system boots it passes
mode=620, overriding the default
mode, so I've put that in the command line above in the interest of better restoring the default functionality of /dev/pts.
- Don't set
uid. It will lead you either to security problems or to the same problem of terminals not spawning.
newinstance is optional, but can improve security. With this option, containers can't mount the "real"
/dev/pts because the host system isn't using it. If this is used, you should ensure
ptmxmode=666 and that
/dev/ptmx is a symlink to
pts/ptmx. Mounting a new
devpts instance over
/dev/pts may cause strange behaviours in existing terminals (e.g.
gpg not working), so you should restart those if you use this option.