output to closed control tty [was Re: Reparenting processes?]
> I'll be testing more with real hardware. I've now tried: 5.2/amd64 with com0 at acpi0 (UAR1, PNP0501-0): io 0x3f8-0x3ff irq 4 com0: ns16550a, working fifo 1.4T/sparc with zs0 at obio0 slot 0 offset 0x10 level 12 softpri 6 zstty1 at zs0 channel 1 In each case, I get EIO with nothing output to the port. /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Re: Reparenting processes?
> I think I have a USB serial port somewhere. I should try that under > 5.2 to see what happens. When pointed at /dev/ttyU0, ctty-test prints ctty-test: test write failed: Input/output error but, curiously, one CRLF does get emitted to /dev/ttyU0. It also leaves it in a peculiar state in which the next character written to it gets lost - or, at least, that's the best short description of what I saw. Specifically, I ran # ctty-test /dev/ttyU0 and I got the EIO indication (plus "exit 1" because of the "setsid broken for pgrp leaders" workaround) and a CRLF sent down the serial line. Then I ran serialconsole, a program of mine which is designed to talk to, well, serial consoles, but which can also be used as a way to just talk to a tty. Using that, I then typed "xyz" at it. The x disappeared; the y and z showed up as normal. Further typing appears to work normally. Apparently 5.2's ucom's write routine does not work right when the device is not actually open. Given how complex USB is, this does not surprise me; what surprises me is that _anything_ gets through, and the peculiar character-eating state it gets left in. It does make me glad I did that test on a machine for which a crash or hang would not have been more than a minor inconvenience; there clearly are issues with at least some serial port drivers under this circumstance. If someone can reproduce this under 9.1, perhaps filing a PR would be a good idea? I'll be testing more with real hardware. /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Re: Reparenting processes?
>> This makes me wonder if perhaps login sessions should have their >> stdin/stdout/stderr set up on /dev/tty instead of the actual ctty >> device. > Interesting. Need to think about that... One thing I can remark on already: tty(1) and ttyname(3) become less useful, at least as they are currently implemented. When I run $SHELL with stdin, stdout, and stderr connected to /dev/tty, then tty(1), which is basically just a thin wrapper around ttyname(3), prints /dev/tty on 1.4T, and does so on 5.2 except for ptys (the exception because of an apparent optimization attempt in ttyname(3)). I'm not sure whether I think tty(1) and/or ttyname(3) should drill through /dev/tty and find the real tty; I can see arguments each way. /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Waiting for Randot (or: nia and maya were right and I was wrong)
[bcc tech-kern, tech-security, tech-crypto; followups to tech-userlevel to keep discussion in one place] Many of you have no doubt noticed that a lot more things hang waiting for entropy than used to on machines without hardware random number generators (even as we've added a bunch of new drivers for HWRNGs) -- e.g., python, firefox. This is related to the adoption of the getrandom system call from Linux, which we adopted with the semantics that getrandom(p,n,0) will block until the kernel is certain there is enough entropy for security. In retrospect, based on experience with the change, such as the following threads and bugs (as well as many private discussions on IRC), I think adopting getrandom with this semantics was a mistake: https://gnats.NetBSD.org/55641 https://gnats.netbsd.org/55847 https://mail-index.NetBSD.org/current-users/2020/09/02/msg039470.html https://mail-index.NetBSD.org/current-users/2020/11/21/msg039931.html https://mail-index.netbsd.org/current-users/2020/12/05/msg040019.html It's certainly a problem when keys are generated with too little entropy -- e.g., https://factorable.net -- but it's increasingly clear that _the middle of an application trying to get something else done_ is not a good place for hanging until someone plugs in a USB HWRNG. Such an application, like a Python program in the middle of just doing `import multiprocessing', is not in a position to remedy the situation or even usefully alert an operator to the problem. To better address the system integration, I added hooks in /etc/rc and /etc/security for alerting the operator to the problem with entropy: - setting `entropy=check' in /etc/rc.conf will abort multiuser boot and enter single-user mode if there's not enough entropy before starting any network services (or setting `entropy=wait' will make multiuser boot hang -- caveat: possibly indefinitely) - the daily /etc/security script will check for entropy and send an alert citing the new entropy(7) man page in the security report We might also do something similar with the motd -- add a single line, citing entropy(7) for more details, if there's not enough entropy. With these in mind, I propose that we change getrandom(p,n,0) so that it does not block -- under the premise that dealing with low entropy is a system integration problem, not a problem that it is helpful to ask an application to resolve in the heat of the sampling moment. Programs can still poll /dev/random (or getrandom(p,n,GRND_RANDOM)), if testing for entropy is actually their goal, but the default recommended choice for all applications to generate keys, which is getrandom(p,n,0), will not. I also propose we introduce never-blocking getentropy like nia@ briefly did last year, as an alias for getrandom(p,n,0) soon to be in POSIX (https://www.austingroupbugs.net/view.php?id=1134), under the premise that the never-block semantics (from the original in OpenBSD) is justified again by treating low entropy as a system integration problem. Thoughts? P.S. Previous discussions about getrandom, getentropy, blocking, and changes to the kernel entropy subsystem for NetBSD 10: https://gnats.NetBSD.org/55659 https://mail-index.NetBSD.org/tech-userlevel/2020/05/02/msg012333.html https://mail-index.NetBSD.org/current-users/2020/05/01/msg038495.html https://mail-index.NetBSD.org/tech-kern/2019/12/21/msg025876.html
Re: Reparenting processes?
>> I've got the test program written. On 5.2/amd64 with /dev/ttyE1 as >> the test tty (no getty running on it, of course), output works just >> fine [...] > I tried it too, on 9.1 amd64, and that worked too. I did not expect > that. While trying to write down why I thought that, I got even more > confused for a while, because there is stuff going on both with > vnodes for the ctty, and pointers to its struct tty, and they are not > handled together. True. > I'm looking at current-ish source, but I suppose this hardly ever > changes. I agree, because the code you quote looks a whole lot like the corresponding 5.2 code, including the split of TIOCSCTTY's functionality between tty.c and vfs_vnops.c. > I wonder what happens if a USB serial port is the ctty and it gets > removed... probably a dangling pointer. I think I have a USB serial port somewhere. I should try that under 5.2 to see what happens. Some parts of the tty code likely date from before dynamic detach and thus may not handle it well > so you can conceivably set a FIFO or a block device or a random raw > disk also as controlling tty? If its ioctl routine accepts TIOCSCTTY, yes. I would almost say that accepting TIOCSCTTY is the defining characteristic of things capable of becoming cttys...though not quite, because without a struct tty, it gets a bit confused. I suppose something accepting TIOCSCTTY without setting s_ttyp simply counts as a driver bug > Why the code for TIOCSCTTY is split in two parts remains unclear. To put it mildly! :-) > Maybe the existence of this split explains why session leaders are > not allowed to relinquish their ctty using TIOCNOTTY That made no sense to me either. Neither does the test that forbids process group leaders from setsid()ing. > [Stevens] "Advanced Programming in the UNIX Environment" from Stevens > is more explanatory about sessions etc (but it also says that BSD has > no session IDs, but by now NetBSD clearly does have them). At the time, I think, BSD did not have them. My impression is that POSIX created them by fiat, though presumably it actually drew them from somewhere. I'm not sure whether I think sessions are a good thing or not. > "... the hang-up signal is sent to the controlling process (the > session leader)" Really? I thought tty-generated SIGHUPs were sent to all processes in the tty's pgrp, regardless of sessions. Perhaps I need to go read more code. /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Re: Reparenting processes?
On Sun 10 Jan 2021 at 10:25:10 -0500, Mouse wrote: > I've got the test program written. On 5.2/amd64 with /dev/ttyE1 as the > test tty (no getty running on it, of course), output works just fine > (this doesn't surprise me; I find it plausible that wscons tty > open/close are pretty much no-ops aside from possible permissions > checking on open). I tried it too, on 9.1 amd64, and that worked too. I did not expect that. While trying to write down why I thought that, I got even more confused for a while, because there is stuff going on both with vnodes for the ctty, and pointers to its struct tty, and they are not handled together. (I also tried on Linux Ubuntu 20.10 and that worked too... just needed a small change to compile) I'm looking at current-ish source, but I suppose this hardly ever changes. This in /sys/kern/tty_tty.c works with vnodes: #define cttyvp(p) ((p)->p_lflag & PL_CONTROLT ? (p)->p_session->s_ttyvp : NULL) static int cttywrite(dev_t dev, struct uio *uio, int flag) { struct vnode *ttyvp = cttyvp(curproc); int error; if (ttyvp == NULL) return (EIO); vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_WRITE(ttyvp, uio, flag, NOCRED); VOP_UNLOCK(ttyvp); return (error); } and of course my expectation was that this vnode pointer would be NULLed out somehow when the process closes the tty. In /sys/kern/tty.c, for TIOCSCTTY, there is no vnode pointer being set (s_ttyvp !) but only a struct tty * (s_ttyp !). I see no added reference count on the struct tty * for the tty that is about to become a ctty. I wonder what happens if a USB serial port is the ctty and it gets removed... probably a dangling pointer. case TIOCSCTTY: /* become controlling tty */ mutex_enter(_lock); mutex_spin_enter(_lock); /* Session ctty vnode pointer set in vnode layer. */ if (!SESS_LEADER(p) || ((p->p_session->s_ttyvp || tp->t_session) && (tp->t_session != p->p_session))) { mutex_spin_exit(_lock); mutex_exit(_lock); return (EPERM); } /* * `p_session' acquires a reference. * But note that if `t_session' is set at this point, * it must equal `p_session', in which case the session * already has the correct reference count. */ if (tp->t_session == NULL) { proc_sesshold(p->p_session); } tp->t_session = p->p_session; tp->t_pgrp = p->p_pgrp; p->p_session->s_ttyp = tp; // struct tty *tp p->p_lflag |= PL_CONTROLT; mutex_spin_exit(_lock); mutex_exit(_lock); break; strangely enough, I finally found the setting of p->p_session->s_ttyvp in kern/vfs_vnops.c: case VFIFO: case VCHR: case VBLK: error = VOP_IOCTL(vp, com, data, fp->f_flag, kauth_cred_get()); if (error == 0 && com == TIOCSCTTY) { vref(vp); mutex_enter(_lock); ovp = curproc->p_session->s_ttyvp; curproc->p_session->s_ttyvp = vp; mutex_exit(_lock); if (ovp != NULL) vrele(ovp); } return (error); so you can conceivably set a FIFO or a block device or a random raw disk also as controlling tty? At least it does reference counting here. Why the code for TIOCSCTTY is split in two parts remains unclear. I searched for other devices to handle the lower half of it and found none (it wouldn't make sense anyway). Neither is [4.3BSD] "The Design and Implementation of the 4.3BSD UNIX Operating System" illuminating; its chapter 9 on Terminal handling hardly mentions details about process groups, and sessions not at all. [FBSD] "The Design and Implementation of the FreeBSD Operating System (Version 5.2)" at least briefly describes sessions (section 10.5) but doesn't explain any of this either. Maybe the existence of this split explains why session leaders are not allowed to relinquish their ctty using TIOCNOTTY (because it messes with the current reference counting): kern/tty_tty.c: cttyioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) { struct vnode *ttyvp = cttyvp(l->l_proc); ... if (cmd == TIOCNOTTY) { mutex_enter(_lock); if (!SESS_LEADER(l->l_proc)) { l->l_proc->p_lflag &= ~PL_CONTROLT; rv = 0; } else rv = EINVAL; mutex_exit(_lock); return (rv);
Re: Reparenting processes?
> The case I'm wondering about is: > - open real tty > - make it the control tty > - open /dev/tty > - close the real tty > - read/write the /dev/tty fd > It looks to me as though this could lead to the underlying tty driver > getting a read/write call when, according to its open/close calls, > it's not open. I've got the test program written. On 5.2/amd64 with /dev/ttyE1 as the test tty (no getty running on it, of course), output works just fine (this doesn't surprise me; I find it plausible that wscons tty open/close are pretty much no-ops aside from possible permissions checking on open). I'm going to test with real hardware on 5.2/amd64 and 1.4T/sparc, but those will not be happening as immediately. The test program is in ftp.rodents-montreal.org:/mouse/misc/ctty-test.c in case anyone wants to try it on other versions or other hardware. /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Re: Reparenting processes?
>> It actually occurs to me that this is a potential problem even >> today: what happens if all the processes in a session close the >> descriptors they have on the ctty, and there are no others lying >> around in other [...] > or similarly, if they TIOCNOTTY it (although tty(4) tells me it's > obsolete) That would be testing something else. The case where a process has no ctty is comparatively well understood. I'm wondering about the case where a process has a ctty but the real ctty device is not open. > I think sys/kern/tty_tty.c is the implementation of /dev/tty, and it > seems you get ENXIO. That's what I see for open on /dev/tty if there is no ctty. (I/O on /dev/tty when there's no ctty returns EIO in the code I have at hand.) The case I'm wondering about is: - open real tty - make it the control tty - open /dev/tty - close the real tty - read/write the /dev/tty fd It looks to me as though this could lead to the underlying tty driver getting a read/write call when, according to its open/close calls, it's not open. I suspect it's a case that has never been tested; indeed, until this discussion, the possibility had never occurred to me. /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Re: Reparenting processes?
On Sun 10 Jan 2021 at 09:44:18 -0500, Mouse wrote: > >> This makes me wonder if perhaps login sessions should have their > >> stdin/stdout/stderr set up on /dev/tty instead of the actual ctty > >> device. But if that's done, will the `real' ctty device even be > >> open? [...] > > It actually occurs to me that this is a potential problem even today: > what happens if all the processes in a session close the descriptors > they have on the ctty, and there are no others lying around in other or similarly, if they TIOCNOTTY it (although tty(4) tells me it's obsolete) > processes, and then one of those processes tries to access /dev/tty? > It would be an unusual session, true, but there's nothing preventing it > from happening as far as I can see. Would the underlying tty driver > explode upon getting I/O calls when it isn't open, or what? I think sys/kern/tty_tty.c is the implementation of /dev/tty, and it seems you get ENXIO. Also each read/write call goes to the *current* controlling tty, freshly looked up. > /~\ The ASCII Mouse -Olaf. -- Olaf 'Rhialto' Seibert -- rhialto at falu dot nl ___ Anyone who is capable of getting themselves made President should on \X/ no account be allowed to do the job. --Douglas Adams, "THGTTG" signature.asc Description: PGP signature
Re: Reparenting processes?
>> This makes me wonder if perhaps login sessions should have their >> stdin/stdout/stderr set up on /dev/tty instead of the actual ctty >> device. But if that's done, will the `real' ctty device even be >> open? [...] It actually occurs to me that this is a potential problem even today: what happens if all the processes in a session close the descriptors they have on the ctty, and there are no others lying around in other processes, and then one of those processes tries to access /dev/tty? It would be an unusual session, true, but there's nothing preventing it from happening as far as I can see. Would the underlying tty driver explode upon getting I/O calls when it isn't open, or what? I think I'll build a test program that does this: does setsid(), opens a tty (which would have to not be open by anything else, for the test to be useful), does TIOCSCTTY, opens /dev/tty, closes all its descriptors on the real tty, then accesses its /dev/tty descriptor /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Re: Reparenting processes?
>> This makes me wonder if perhaps login sessions should have their >> stdin/stdout/stderr set up on /dev/tty instead of the actual ctty >> device. But if that's done, will the `real' ctty device even be >> open? [...] > Interesting. Need to think about that... All I've come up with so far is that maybe a session should hold an open on its ctty. It would address this issue, but would it produce others? None come to mind offhand, but then, I didn't think of the file descriptor issues until I got halfway through implementing reparenting /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B