Re: mutilog via fifo

Daryl Tester <[email protected]> Mon, 04 Aug 2008 09:47:50 +0930
Newsgroups gmane.comp.djb.syslog
Message-ID <[email protected]>
richard lucassen wrote:

> What happens (AFAIUI) is that elhttp is trying to write to the fd that
> had been opened by root. Normally it changes ownership of course (Debian
> running a vanilla kernel)

That doesn't matter - as Paul said, access permissions are only checked
when a file is opened, not read or written to.  The sequence goes something
like (this is rough and I haven't verified it against the source), and
apologies if you know some/most/all of this in advance:

svscan opens a pair of supervise processes, with a pipe connecting stdout
of the "main" supervise process to the stdin of the "log" supervise process.

The supervise processes fork, then exec their respective run programs
(typically, shell scripts).  From this point on, we're looking at the main
run script.

The run script redirects stderr (fd 2) to fd 1 (stdout), so "error" messages
(typically written to stderr) are written to the pipe to the logging process.

The run script then execs envuidgid, which sets environment variables UID GID,
which in turn execs tcpdaemon.

tcpdaemon listens on a socket.  When a connection establishes, it forks, sets
sets up fd 0 & 1 onto the incoming connection, setuid to the UID supplied,
then execs the elhttp process.

At this point, elhttp is running as the non-root user, fd 2 has been
inherited from the run script (the same as the original fd 1, which is
the pipe to multilog), and fd 0 & 1 is now the write half of the network
connection.

> And elhttp runs under its own uid, which is set by tcpserver (-U
> option). I think elhttp is writing to its "own" stderr, and that's
> a different pipe.

Through inheritance, it should be the same descriptor as was passed
into tcpserver (which we now know was passed in as fd 1 to the run
script).  /dev/stderr should return this file descriptor upon opening,
but it appears to be having some issue (possible caused by the change
in uid).

> I agree, normally there is the name of the logfile. Have a look at it,
> it's a very small proxy for embedded systems:
> 
> http://dl.xaq.nl/linux/elhttp/

Well, the patch to make it work with stderr is "simple" (too simple -
the original didn't check for failure upon opening, which would have
shown up your issue with using /dev/stderr earlier).  Go to line 80,
change (warning, untested) and recompile:

  td.logfile = ( argc > 4 ) ? fopen( argv[4], "a+" ) : NULL;

to read:

  td.logfile = ( argc > 4 ) ? fdopen(2, "w") : NULL;
  setvbuf(td.logfile, (char *) NULL, _IONBF, 0);

(the setvbuf is to force the output to be unbuffered - I'm a mistrusting
soul).

I'm still intrigued as to why the open of /dev/stderr is failing though.


Cheers,
  --dt