[syslog-ng]Re: Bug #161915
Balazs Scheidler
bazsi@balabit.hu
Fri, 4 Oct 2002 10:54:59 +0200
On Thu, Oct 03, 2002 at 04:09:27PM -0700, Brian Thomas wrote:
> On Thu, Oct 03, 2002 at 12:54:41PM +0200, Balazs Scheidler wrote:
> > Hi,
> >
> > Thanks for the information you provided.
> >
> > The problem is that the programs do not send \n at the end of line while
> > syslog-ng expects one for STREAM oriented sources. (such as unix-stream),
>
> This seems like a bug in the packages like cron, I would think. If using
> a stream source I'd think the daemon would be expected to provide
> \n's?
libc should do that. there's nothing saying that syslog() calls should be
made with a string terminated with NLs.
>
> >
> > Earlier versions of syslog-ng took a message as a full message in the
> > following cases:
> > 1) either NL or NUL was found in the incoming stream
> > 2) after a single read and the source is datagram oriented (UDP or unix-dgram)
> > 3) after the incoming buffer is full (specified via log_msg_size())
> >
> > For stream oriented sources either 1) or 3) must be true. The strace you
> > sent me indicates that some programs do not terminate their messages by
> > '\n'.
> >
> > Checking out the libc sources shows that libc automatically terminates
> > messages by NL if LOG_PERROR is set, and also adds a \0 at the end of the
> > line if STREAM sockets are used. So both syslog-ng and libc behaviour seems
> > to be correct. Something must be wrong anyway as the strace didn't show
> > terminating NUL characters.
> >
> > I assumed that you are using unix-stream sources, but this assumption
> > should be true as syslog-ng issues read() instead of recvfrom().
>
> I should have provided my syslog-ng.conf. Here's the sources line:
>
> source src { unix-dgram("/dev/log"); internal(); file("/proc/kmsg"
> log_prefix("kernel: ")); udp(); };
>
> So no, I'm not using streams, I'm using sockets. And this is
> interesting, because this was the default .conf that was installed, and
> from looking at the man page I'd think that should be
> unix-socket("/dev/log"), right?
hmm... unix-dgram sources should call recvfrom and not read. I verified this
and they do indeed use recvfrom. (I've just found a bug in the kernel,
it returns bogus sockaddrs from recvfrom on SOCK_DGRAM sockets)
I workaround in libol is now available at the end of this message. I've also
attached the kernel patch that should fix the problem.
> > As syslog-ng reads no terminating NUL characters, I think this should be a
> > libc issue. stream sockets should always have line terminations, as it is
> > not guaranteed by the kernel that a single write will be read by single read
> > calls.
> >
> > I don't know where to submit this bug, to the libc people, or to the cron
> > people?
>
> Assuming that my confusion about unix-dgram vs. unix-stream is just me
> being confused, and that I'm using streams even when I specify
> unix-dgram, than I would think this is a cron issue. It seems like
> they're being sloppy in their logging.
can you check lsof -p <syslogng pid>
just to see what fd 3 is ?
If it is really a unix-dgram socket, it should not be read by read()
syslog-ng should have used recvfrom() instead. On my testbox it correctly
used recvfrom.
PS: please Cc syslog-ng@lists.balabit.hu in followups.
Kernel patch, which fixes the unix domain socket issue (against 2.4.18):
--- af_unix.c~ Mon Feb 25 20:38:16 2002
+++ af_unix.c Fri Oct 4 09:46:26 2002
@@ -1392,6 +1392,9 @@
sk->protinfo.af_unix.addr->name,
sk->protinfo.af_unix.addr->len);
}
+ else {
+ ((struct sockaddr *) msg->msg_name)->sa_family = AF_UNIX;
+ }
}
static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, int size,
Libol patch, which works around the problem above:
diff -u -r1.28 io.c
--- io.c 16 Sep 2002 08:23:22 -0000 1.28
+++ io.c 4 Oct 2002 08:53:41 -0000
@@ -368,7 +368,16 @@
}
for (;;) {
- int res = recvfrom(closure->fd, buffer, length, 0, (struct sockaddr *) addr, (socklen_t *) addrlen);
+ int res;
+
+ res = recvfrom(closure->fd, buffer, length, 0, (struct sockaddr *) addr, (socklen_t *) addrlen);
+
+ if (*addrlen == 2) {
+ /* HACK: this is a workaround of a Linux 2.2 & 2.4 bug,
+ * it doesn't return anything sensible in sockaddr buf
+ */
+ ((struct sockaddr *) addr)->sa_family = AF_UNIX;
+ }
if (res == 0) {
/* on SOCK_DGRAM protocols 0 returned bytes doesn't mean anything */
--
Bazsi
PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1