Page MenuHomeFreeBSD

ttymsg: Overhaul
ClosedPublic

Authored by des on Fri, May 15, 4:15 PM.
Tags
None
Referenced Files
F157895180: D57018.id.diff
Tue, May 26, 6:32 AM
Unknown Object (File)
Mon, May 25, 9:11 PM
Unknown Object (File)
Mon, May 25, 8:19 PM
Unknown Object (File)
Mon, May 25, 7:49 PM
Unknown Object (File)
Mon, May 25, 7:47 PM
Unknown Object (File)
Mon, May 25, 5:57 PM
Unknown Object (File)
Mon, May 25, 11:39 AM
Unknown Object (File)
Mon, May 25, 12:47 AM

Details

Summary
  • Instead of an error string, return the usual 0 or -1 and let the caller figure out what, if anything, to tell the user.
  • Avoid string manipulations by opening /dev first and using openat() with O_RESOLVE_BENEATH.
  • Add a boolean argument which, if false, causes ttymsg() to return without sending the message if the tty's group-writable bit is not set. This saves programs that respect this setting (like syslogd(8)) from having to check before calling ttymsg().
  • Update all callers.

The observable effect of this change is minimal except for slightly
different error messages when ttymsg() fails. However, syslogd(8) will
no longer print spurious error messages on the console after trying and
failing to write a log message to an X11 session.

PR: 295171
MFC after: 1 week

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 73320
Build 70203: arc lint + arc unit

Event Timeline

des requested review of this revision.Fri, May 15, 4:15 PM

Is it enough to check the first character? In other words: Is it impossible to have something in front
of the ':' (like "localhost" or whatever)? That's why I used strchr() in my bug report...

usr.sbin/syslogd/syslogd.c
2152

Why not instead check whether /dev/ut->ut_line exists?

usr.sbin/syslogd/syslogd.c
2152

It's nontrivial and repeats work later done by ttymsg(). I think it's time the latter got a glow-up...

des retitled this revision from syslogd: Don't try to write to X11 sessions to ttymsg: Overhaul.Mon, May 18, 2:21 PM
des edited the summary of this revision. (Show Details)
des edited the summary of this revision. (Show Details)

redo

usr.bin/wall/ttymsg.c
84

This leaks fd if fstat() fails.

usr.sbin/syslogd/syslogd_cap_log.c
139

Shouldn't we nvlist_get_boolean(nvlin, "shout") here?

144

I think you're supposed to pack this error value into nvlout? Returning a non-zero value to the caller here raises an error to the casper library rather than to the caller.

des marked 4 inline comments as done.Tue, May 19, 9:12 PM
des added inline comments.
usr.sbin/syslogd/syslogd_cap_log.c
139

Good catch, thank you.

des marked an inline comment as done.

rf

usr.sbin/syslogd/syslogd.c
2152

Do you still need this check?

des marked an inline comment as done.Tue, May 19, 9:45 PM
des added inline comments.
usr.sbin/syslogd/syslogd.c
2152

No, I'd just forgotten about it.

des marked an inline comment as done.

rf

markj added inline comments.
usr.sbin/syslogd/syslogd_cap_log.c
113

I think the nvlist_destroy() and logerror() calls below could clobber errno.

This revision is now accepted and ready to land.Wed, May 20, 1:33 PM
des marked an inline comment as done.Thu, May 21, 1:26 PM
des added a subscriber: oshogbo.

@oshogbo can you please review the changes to the Casper code?

This revision now requires review to proceed.Thu, May 21, 1:27 PM

For you, always, des :)

usr.bin/wall/ttymsg.c
50–54

Small nite: I guess we can drop double spaces.

68–70

Nite: I guess you can use nitems here.

usr.sbin/syslogd/syslogd_cap_log.c
142

I think this is won't work.
Libcasper handles the error handling:
https://github.com/freebsd/freebsd-src/blob/a2f733abcff64628b7771a47089628b7327a88bd/lib/libcasper/libcasper/service.c#L319-L324

So creating a duplicate "error" entry will brake libnv communication. So I guess you should do:

if (ttymsg(iov, iovcnt, line, tmout, shout) != 0) {
  serror = errno;
  free(iov);
  return (serror);
}
usr.sbin/syslogd/syslogd_cap_log.c
142

That's what I suspected. In that case I think cap_p_open() / casper_p_open() is incorrect as well.

To be clear, error contains the return value from the casper_*() function if and only if it is not zero, right?

usr.sbin/syslogd/syslogd_cap_log.c
142

Furthermore, cap_p_open() / casper_p_open() probably belong somewhere else, maybe in cap_fileargs() or maybe in its own Casper service, but let's leave that for later.

usr.bin/wall/ttymsg.c
50–54

Double spaces are necessary to distinguish the period at the end of a sentence from the period at the end of an abbreviation within a sentence (this is also why *roff and mandoc require sentences to start on a new line).

usr.sbin/syslogd/syslogd_cap_log.c
142

To be clear, error contains the return value from the casper_*() function if and only if it is not zero, right?

The error is always added - when the function is called. If the function return 0 then it is 0.

usr.sbin/syslogd/syslogd_cap_log.c
88

This should return an error code, not -1, but I'm not sure which. ECAPMODE perhaps?

usr.bin/wall/ttymsg.c
57

Is there a reason why we don't just make iovcnt a size_t while we're here?

57

I think we should rename the line parameter to something like tty. I needed to go and look at callsites to understand was supposed to be passed here. I understand it means line in the context of a serial line, but that wasn't immediately clear to me.

80

You removed the comment explaining why we don't return error on EBUSY and EACCES. I don't like this behavior, but if we're going to keep it, keep the explanation as well.

131

close might clobber errno here

usr.bin/wall/wall.c
162

Since ttymsg preserves errno now, we can use warn instead of warnx

usr.sbin/syslogd/syslogd_cap_log.c
88

I don't know if I'd call this a capability mode violation (which is what ECAPMODE is used for). Maybe just ENOENT since a matching filed couldn't be found.

102–103

Is there a reason you changed this from tmout to timeout? The surrounding context already uses tmout

While we're here, maybe steal NetBSD's ttymsg man page and adapt it for these changes? https://man.netbsd.org/ttymsg.3

des marked 9 inline comments as done.Fri, May 22, 5:16 PM

While we're here, maybe steal NetBSD's ttymsg man page and adapt it for these changes? https://man.netbsd.org/ttymsg.3

We don't provide ttymsg(3).

usr.bin/wall/ttymsg.c
57

Is there a reason why we don't just make iovcnt a size_t while we're here?

writev() takes an int.

usr.sbin/syslogd/syslogd_cap_log.c
88

Exacly, it's a capability mode violation because we're trying to popen() a program that's not on the preapproved list.

102–103

I find the abbreviation confusing, especially next to shout which is not an abbreviation but happens to differ only by its first two letters, and this is not a situation where brevity would be preferred over clarity.

des marked 3 inline comments as done.Fri, May 22, 5:16 PM
In D57018#1310291, @des wrote:

We don't provide ttymsg(3).

It is strange that talkd, syslogd, and wall all reference usr.bin/wall/ttymsg.c. It would make sense to follow NetBSD's lead and add it into a library for more idiomatic usage. This is a problem for another day though.

usr.sbin/syslogd/syslogd_cap_log.c
88

I suppose it depends on what you classify as a capability violation.

I always classified capability violations as actions that directly try to break the kernel-level sandbox. With my logic, ECAPMODE should only originate from the kernel.

This would be a program-defined capability violation since the rule we're breaking exists only in the syslogd code (the piped command must have a valid filed in the filed list).

I'm ok with this interpretation. I just wanted to highlight the distinction.

This revision is now accepted and ready to land.Mon, May 25, 4:00 PM
usr.sbin/syslogd/syslogd_cap_log.c
126

Small nit. If we're going with timeout instead of tmout, then maybe we should stay consistent and use timeout everywhere. Or at the very least, here, since it is new code.

This revision was automatically updated to reflect the committed changes.