becker@trantor.harris-atd.com (Don Becker) (12/16/88)
I changed our version of ftpd to do logging, and also ran into the syslog() lossage over chroot(). At the bottom of my message is a bug report, to clarify the issue for newcomers. I installed a fix similar to the one suggested by Tad Guy <tadguy@cs.odu.edu>. A quick look at his change suggests that he doesn't deal with the case where a connect() is not done -- he always has syslog() do a send() rather than a sendto() to the socket. Recall that, as the manual states, Send may be used only when the socket is in a connected state, while sendto and sendmsg may be used at any time. Thus some provision should be made (a flag variable) to indicate the connect() has not been done, and that a sendto() should be used instead. Making a connection is the Right Thing, and should be default. It should be more efficient than doing namei() on "/dev/log" each time inside of sendto, but I suspect that it isn't. A potential fix is to record the absolute pathname in the kernel table whenever a UNIX domain socket is made, however this might not be considered a "simple fix" by most people. Bug report _________________ Bug: syslog() fails silently after/across chroot() calls. sendto() has an undocumented error value (ENOENT) on unix domain sockets Cause: syslog() uses UNIX domain datagrams to communicate, and for each sendto() the unix domain socket address is looked up again. When a chroot() is done the AF_UNIX address "/dev/log" is invalid. Fix: At the very least this behavior should be documented. An additional flag to openlog could specify Internet domain instead of UNIX domain datagrams. Syslogd already listens there for log messages from other machines. Unix domain sockets could record the absolute pathname rather than just the pathname relative to the current root directory. Questions and comments: It is clear why UNIX domain datagrams have this behavior, but it means they have to do the namei() lookup on the address (pathname) for every datagram, doesn't it? At a higher level, openlog() implies that something analogous to an open happens, and open files remain valid across chroot() calls. Even in looking at the source to syslog() it isn't clear that the file descriptor for the socket could become invalid after a chroot(). Pity the sites without source licenses. -- Donald Becker Advanced Technology Department becker@trantor.harris-atd.com Government Systems Sector (407) 729-7303 Harris Corporation, Melbourne, FL. 32905
tadguy@cs.odu.edu (Tad Guy) (12/16/88)
In article <17826@adm.BRL.MIL>, becker@trantor (Don Becker) writes: >I installed a fix similar to the one suggested by Tad Guy ><tadguy@cs.odu.edu>. A quick look at his change suggests that he >doesn't deal with the case where a connect() is not done -- he always >has syslog() do a send() rather than a sendto() to the socket. I considered this, and unless I am reading the source wrong, connect() is guaranteed to have been called before the send(). Even if you call syslog() without first calling openlog() (or after calling openlog() but without LOG_NDELAY set), syslog() calls openlog() for you with LOG_NDELAY set, thus guarantying that the socket is created and (with my patch) connected before any calls to send() occur. This is with the 4.3BSD syslog.c (version 5.9 dated 5/7/86). Your version may be different. >Making a connection is the Right Thing, and should be default. It >should be more efficient than doing namei() on "/dev/log" each time >inside of sendto, but I suspect that it isn't. It is. But, as Louis Mamakos pointed out, doing the connect() is a bad idea for long running processes, because they run the risk of having the inode info for an obsolete "/dev/log" should syslogd be restarted. ...tad -- Tad Guy <tadguy@cs.odu.edu> Old Dominion University, Norfolk, VA