output to closed control tty [was Re: Reparenting processes?]

2021-01-10 Thread Mouse
> 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?

2021-01-10 Thread Mouse
> 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?

2021-01-10 Thread Mouse
>> 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)

2021-01-10 Thread Taylor R Campbell
[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?

2021-01-10 Thread Mouse
>> 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?

2021-01-10 Thread Rhialto
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?

2021-01-10 Thread Mouse
> 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?

2021-01-10 Thread Mouse
>> 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?

2021-01-10 Thread Rhialto
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?

2021-01-10 Thread Mouse
>> 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?

2021-01-10 Thread Mouse
>> 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