daemon@watale.waterloo.edu (Watale's Little Helper) (11/27/88)
I have been having trouble trying to get in.ftpd to record all anonymous ftp activity. I don't quite understand why, but the problem seems to be caused by the chroot call. A trace of in.ftpd shows the following: [all writes to descriptor three (/dev/log) work fine above this point] chdir ("/usr/ftp") = 0 open ("/usr/adm/wtmp", 011, 0) = 4 chroot ("/usr/ftp") = 0 write (1, "230 Guest login ok, access restr".., 48) = 48 gettimeofday (0xf7fff388, 0) = 0 getpid () = 6019 [crash, and burn time] sendto (3, "<31>Nov 25 22:32:07 ftpd[6019]: ".., 42, 0, 0xd4e8, 16) = -1 ENOENT (No such file or directory) It seems that altering the root directory somehow messes up access to /dev/log. I suppose the obvious answer is that /dev/log is no longer accessible once the chroot("/usr/ftp") takes effect. But there must be more to it than that, because /dev/log is opened before the root directory is changed*. * It is my understanding that I can open any file, do a chroot, and still have access to that file until I close it (even if it lies "above" the new root directory). Does this statement not hold true for UNIX domain sockets like /dev/log? And if so, why? Assuming that there really is a problem, and I'm not just being dense, how can I fix in.ftpd to properly log messages after calling chroot? Thank you for your time. Mike Adams mdadams@surya.waterloo.edu
guy@auspex.UUCP (Guy Harris) (11/29/88)
>* It is my understanding that I can open any file, do a chroot, and >still have access to that file until I close it (even if it lies "above" >the new root directory). Does this statement not hold true for UNIX >domain sockets like /dev/log? No, if I read the 4.3BSD code correctly, it doesn't. For one thing, you don't open UNIX-domain sockets (fixed in 4.4BSD?); you do a "socket" call that creates a socket that refers to the UNIX-domain protocol/address family in general, not to some particular "address" in that family, and then either do a "connect" call to bind it to a particular address, or specify the address in a "sendto" call. That's the point at which the "address" - which, in the UNIX-domain case, is the pathname of a file such as "/dev/log" - is interpreted, and if that happens after the "chroot", you lose. >Assuming that there really is a problem, and I'm not just being >dense, how can I fix in.ftpd to properly log messages after calling chroot? It's "syslog" that needs fixing; it should do a "connect" in "openlog", right after it's created the socket. Then just make sure "in.ftpd" does an "openlog" before doing the "chroot". In fact, the 4.3-tahoe "openlog" does precisely that; if the "connect" fails, it notes that it is not connected, and tries to do a "connect" when it does a "syslog". (The intent behind that is presumably so that you can call "openlog" before "syslogd" has started up and created the "/dev/log" socket, and not have it fail, just have it retry later when "syslogd" may be up and running.)
mouse@mcgill-vision.UUCP (der Mouse) (12/14/88)
In article <3024@watale.waterloo.edu>, daemon@watale.waterloo.edu (Watale's Little Helper) writes: > I have been having trouble trying to get in.ftpd to record all > anonymous ftp activity. I don't quite understand why, but the > problem seems to be caused by the chroot call. > A trace of in.ftpd shows the following: [...] > chroot ("/usr/ftp") = 0 [...] > [crash, and burn time] > sendto (3, "<31>Nov 25 22:32:07 ftpd[6019]: ".., 42, 0, 0xd4e8, 16) = -1 > ENOENT (No such file or directory) Aha. That's a sendto(), which passes the address ("/dev/log") at the time of the sendto(), which is after the chroot. And after the chroot, there is no /dev/log. And even if there were, it wouldn't be the one syslogd is listening to. Normally, syslog() would then write it to the console, but /dev/console doesn't exist either. What we need is a syslogd that allows tcp connections, or perhaps a connect() on a datagram socket (I think this might work now). > It seems that altering the root directory somehow messes up access to > /dev/log. I suppose the obvious answer is that /dev/log is no longer > accessible once the chroot("/usr/ftp") takes effect. True enough. The path /dev/log no longer points to what it has to point to - the inode that's got syslogd's socket attached to it. > But there must be more to it than that, because /dev/log is opened > before the root directory is changed*. /dev/log isn't opened; you can't open sockets[%]. The filesystem is traversed for /dev/log each time you call syslog() - this is done in the sendto() kernel implementation. > * It is my understanding that I can open any file, do a chroot, and > still have access to that file until I close it (even if it lies > "above" the new root directory). This is perfectly true. > Does this statement not hold true for UNIX domain sockets like > /dev/log? And if so, why? It does hold true; it's just that what's being done (sendto) doesn't open /dev/log once and then use it. It's more nearly equivalent to opening /dev/log, sending, and closing, all within the sendto(). > Assuming that there really is a problem, and I'm not just being > dense, how can I fix in.ftpd to properly log messages after calling > chroot? The proper fix is to rework syslog() and syslogd so they can be made to work even after the client chroot()s. This is probably beyond most people. I don't see any simple fix. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
tadguy@cs.odu.edu (Tad Guy) (12/14/88)
In article <3024@watale.waterloo.edu>, daemon@watale.waterloo.edu writes: >> [ describes how logging info from ftpd is lost after the chroot() ] In article <1379@mcgill-vision.UUCP>, mouse@mcgill-vision (der Mouse) writes: >That's a sendto(), which passes the address ("/dev/log") at the >time of the sendto(), which is after the chroot. And after the chroot, >there is no /dev/log. > ... >What we need is a syslogd that allows tcp connections, or perhaps a >connect() on a datagram socket (I think this might work now). Yes, this does work in 4.3BSD. >The proper fix is to rework syslog() and syslogd so they can be made to >work even after the client chroot()s. This is probably beyond most >people. I don't see any simple fix. What I did was to connect() the datagram socket to "/dev/log" at the time of openlog() if LOG_NDELAY was specified, then just use send(). Don't forget to add LOG_NDELAY to the openlog() call in ftpd.c. My diffs (your line numbers may vary): *** /usr/src/lib/libc/gen/syslog.c Wed May 7 18:18:50 1986 --- syslog.c Tue Dec 6 20:02:27 1988 *************** *** 120,126 **** c = MAXLINE; /* output the message to the local logger */ ! if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0) return; if (!(LogStat & LOG_CONS)) return; --- 120,126 ---- c = MAXLINE; /* output the message to the local logger */ ! if (send(LogFile, outline, c, 0) >= 0) return; if (!(LogStat & LOG_CONS)) return; *************** *** 167,172 **** --- 167,173 ---- strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data); if (LogStat & LOG_NDELAY) { LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); + connect(LogFile, &SyslogAddr, sizeof SyslogAddr); fcntl(LogFile, F_SETFD, 1); } } -- Tad Guy Comp Sci, Old Dominion University, Norfolk, VA 23529-0162 tadguy@cs.odu.edu tadguy@xanth.cs.odu.edu [128.82.8.1] tadguy@xanth.uucp "Think twice before speaking, but don't say `think think click click'." -- John Owens
tadguy@cs.odu.edu (Tad Guy) (12/14/88)
In article <3024@watale.waterloo.edu>, daemon@watale.waterloo.edu writes: >> [ describes how logging info from ftpd is lost after the chroot() ] In article <1379@mcgill-vision.UUCP>, mouse@mcgill-vision (der Mouse) writes: >That's a sendto(), which passes the address ("/dev/log") at the >time of the sendto(), which is after the chroot. And after the chroot, >there is no /dev/log. > ... >What we need is a syslogd that allows tcp connections, or perhaps a >connect() on a datagram socket (I think this might work now). Yes, this does work in 4.3BSD. >The proper fix is to rework syslog() and syslogd so they can be made to >work even after the client chroot()s. This is probably beyond most >people. I don't see any simple fix. What I did was give ftp its own copy of syslog.c, which I modified to connect() the datagram socket to "/dev/log" at the time of openlog() if LOG_NDELAY was specified, then just use send(). Don't forget to add LOG_NDELAY to the openlog() call in ftpd.c, and don't do this to your system-wide copy of syslog() (as it would break unless openlog() and LOG_NDELAY are used). A more generic solution is needed, but this works fine for ftpd. My diffs (your line numbers may vary): *** /usr/src/lib/libc/gen/syslog.c Wed May 7 18:18:50 1986 --- syslog.c Tue Dec 6 20:02:27 1988 *************** *** 120,126 **** c = MAXLINE; /* output the message to the local logger */ ! if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0) return; if (!(LogStat & LOG_CONS)) return; --- 120,126 ---- c = MAXLINE; /* output the message to the local logger */ ! if (send(LogFile, outline, c, 0) >= 0) return; if (!(LogStat & LOG_CONS)) return; *************** *** 167,172 **** --- 167,173 ---- strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data); if (LogStat & LOG_NDELAY) { LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); + connect(LogFile, &SyslogAddr, sizeof SyslogAddr); fcntl(LogFile, F_SETFD, 1); } } -- Tad Guy Comp Sci, Old Dominion University, Norfolk, VA 23529-0162 tadguy@cs.odu.edu tadguy@xanth.cs.odu.edu [128.82.8.1] tadguy@xanth.uucp "Think twice before speaking, but don't say `think think click click'." -- John Owens
louie@trantor.umd.edu (Louis A. Mamakos) (12/14/88)
In article <6827@xanth.cs.odu.edu> tadguy@cs.odu.edu (Tad Guy) writes: > >What I did was to connect() the datagram socket to "/dev/log" at the >time of openlog() if LOG_NDELAY was specified, then just use send(). >Don't forget to add LOG_NDELAY to the openlog() call in ftpd.c. > I made a change like this in our syslog(); consider what happens to long-lived daemons when /etc/syslogd is restarted for some reason. The socket is no longer connected, and logging ceases. I'd like to see an option to syslog via UDP/SOCK_DGRAM internet sockets, just like 4.2 did. In fact, the code in syslogd is already there for for forwarding log messages to other hosts. All you need is something in the library routine syslog(). Louis A. Mamakos WA3YMH Internet: louie@TRANTOR.UMD.EDU University of Maryland, Computer Science Center - Systems Programming
tadguy@cs.odu.edu (Tad Guy) (12/14/88)
[ My apologies if you've seen this article more than once. I keep finding errors in it and keep superseding it. What a great feature... ] In article <3024@watale.waterloo.edu>, daemon@watale.waterloo.edu writes: >> [ describes how logging info from ftpd is lost after the chroot() ] In article <1379@mcgill-vision.UUCP>, mouse@mcgill-vision (der Mouse) writes: >That's a sendto(), which passes the address ("/dev/log") at the >time of the sendto(), which is after the chroot. And after the chroot, >there is no /dev/log. > ... >What we need is a syslogd that allows tcp connections, or perhaps a >connect() on a datagram socket (I think this might work now). Yes, this does work in 4.3BSD. >The proper fix is to rework syslog() and syslogd so they can be made to >work even after the client chroot()s. This is probably beyond most >people. I don't see any simple fix. What I did was give ftpd its own copy of syslog.c, which I modified to connect() the datagram socket to "/dev/log" at the time of openlog() if LOG_NDELAY was specified, then just use send(). Don't forget to add LOG_NDELAY to the openlog() call in ftpd.c. A more generic solution is needed, but this works fine for ftpd. My diffs (your line numbers may vary): *** /usr/src/lib/libc/gen/syslog.c Wed May 7 18:18:50 1986 --- syslog.c Tue Dec 6 20:02:27 1988 *************** *** 120,126 **** c = MAXLINE; /* output the message to the local logger */ ! if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0) return; if (!(LogStat & LOG_CONS)) return; --- 120,126 ---- c = MAXLINE; /* output the message to the local logger */ ! if (send(LogFile, outline, c, 0) >= 0) return; if (!(LogStat & LOG_CONS)) return; *************** *** 167,172 **** --- 167,173 ---- strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data); if (LogStat & LOG_NDELAY) { LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); + connect(LogFile, &SyslogAddr, sizeof SyslogAddr); fcntl(LogFile, F_SETFD, 1); } } -- Tad Guy Comp Sci, Old Dominion University, Norfolk, VA 23529-0162 tadguy@cs.odu.edu tadguy@xanth.cs.odu.edu [128.82.8.1] tadguy@xanth.uucp "Think twice before speaking, but don't say `think think click click'." -- John Owens
tadguy@cs.odu.edu (Tad Guy) (12/14/88)
In article <3042@haven.umd.edu>, louie@trantor (Louis A. Mamakos) writes: >In article <6827@xanth.cs.odu.edu> tadguy@cs.odu.edu (Tad Guy) writes: >>What I did was to connect() the datagram socket to "/dev/log" at the... > >I made a change like this in our syslog(); consider what happens to >long-lived daemons when /etc/syslogd is restarted for some reason. The >socket is no longer connected, and logging ceases. Sigh, I didn't supersede fast enough... This is correct. What I forgot to mention in that earlier version of my posting was that I gave ftpd its own copy of syslog.c. The moral of the story is not to post either late at night (when the first article went out) or early in the morning (when the superseded artcles went out). Perhaps in midday... ...tad PS: Just for the record I corrected that error the article before I had read Louis' article. :-) -- Tad Guy <tadguy@cs.odu.edu> Old Dominion University, Norfolk, VA