Package: sysklogd Version: 1.4.1-16 Severity: grave Justification: breaks the whole system
References: http://lkml.org/lkml/2005/3/26/37 https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=103392 http://lkml.org/lkml/2004/12/21/208 http://lkml.org/lkml/2004/11/2/17 Syslogd can hang if domark() is called while the main loop is just calling in the ctime() libc function. ctime() is not reentrant and will make syslogd hang (with recent glibc and 2.6 kernels, because glibc uses __libc_lock which uses a [fm]utex). Because AF_UNIX SOCK_DGRAM sockets are blocking by default under Linux, after a short while everything on the system that calls syslog() will hang as well. Which means you can't login anymore, and almost all other network services hang as well. Also cron will fork every now and again and call syslog() so the whole process table will fill up. The system is fubared. The original syslogd protects itself from this by blocking SIGHUP and SIGALRM in logmsg(), but that is under #ifndef SYSV. The attached patch fixes this by adding POSIX sigprocmask calls in logmsg(), as that is the simplest fix. Non-bug related comments: A better fix would be to just set a flag in domark() and check that flag every so often in the mainloop and do the MARKing there. Someone should take out all the #ifdef/#ifndef SYSV stuff and replace it with POSIX routines so that this syslogd compiles under all modern OSes. I think that it doesn't even compile without #define SYSV anymore, anyway. Mike.
--- sysklogd-1.4.1/syslogd.c.ORIG 2005-03-25 22:04:07.360493000 +0100 +++ sysklogd-1.4.1/syslogd.c 2005-03-26 13:28:17.650819246 +0100 @@ -1558,11 +1558,21 @@ int fac, prilev, lognum; int msglen; char *timestamp; +#ifdef linux + sigset_t mask, omask; +#endif dprintf("logmsg: %s, flags %x, from %s, msg %s\n", textpri(pri), flags, from, msg); -#ifndef SYSV +#ifdef linux /* POSIX, really. */ + sigemptyset(&mask); + sigaddset(&mask, SIGHUP); + sigaddset(&mask, SIGALRM); + sigprocmask(SIG_BLOCK, &mask, &omask); +#else +# ifndef SYSV omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM)); +# endif #endif /* @@ -1603,8 +1613,12 @@ (void) close(f->f_file); f->f_file = -1; } -#ifndef SYSV +#ifdef linux + sigprocmask(SIG_SETMASK, &omask, NULL); +#else +# ifndef SYSV (void) sigsetmask(omask); +# endif #endif return; } @@ -1668,8 +1682,12 @@ } } } -#ifndef SYSV +#ifdef linux + sigprocmask(SIG_SETMASK, &omask, NULL); +#else +# ifndef SYSV (void) sigsetmask(omask); +# endif #endif } #if FALSE