Package: syslog-ng
Version: 2.0rc3-1
Severity: important
Tags: patch
(This is the same problem reported against syslog-ng in Gentoo at
https://bugs.gentoo.org/show_bug.cgi?id=154465 -- this contains
a patch which fixes the problem with a similar approach to that
taken in sysklogd.)
When syslog-ng writes to a tty under Linux, for example as a
result of a usertty directive, the write syscall to
/dev/ttyN can ocassionally block indefinitely. One
situation when this occurs is when the user has set XOFF
(perhaps with Ctrl-S or Scroll Lock).
Aside from the fact that this obvious prevents any further
log messages from being written, /dev/log's buffer
eventually fills up causing other programs to block writing
to /dev/log. In extremis, this can render a machine
inaccesible when ssh, etc., all block preventing access.
Reproducible: Always
Steps to Reproduce:
1. Check that there is a usertty("*") directive for (say) kern.emerg logs
2. Ensure syslog-ng is running
3. On console, press Scroll Lock
4. Log something, e.g. logger -p kern.emerg 'Foo'.
5. Repeat #4 many times; eventually it will hang trying to log
-- System Information:
Debian Release: testing/unstable
APT prefers unstable
APT policy: (500, 'unstable'), (500, 'stable')
Architecture: i386 (i686)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.15.2-3
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Versions of packages syslog-ng depends on:
ii libc6 2.3.6.ds1-4 GNU C Library: Shared libraries
ii util-linux 2.12r-11 Miscellaneous system utilities
Versions of packages syslog-ng recommends:
ii logrotate 3.7.1-3 Log rotation utility
-- no debconf information
--- src/afuser.c.orig 2006-11-08 12:36:11.886371656 +0000
+++ src/afuser.c 2006-11-08 13:13:32.133802280 +0000
@@ -27,6 +27,8 @@
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
+#include <signal.h>
+#include <setjmp.h>
typedef struct _AFUserDestDriver
{
@@ -46,6 +48,14 @@
return TRUE;
}
+static sigjmp_buf jmp;
+
+static void alarmproc()
+{
+ signal(SIGALRM, alarmproc);
+ siglongjmp(jmp, 1);
+}
+
static void
afuser_dd_queue(LogPipe *s, LogMessage *msg, gint path_flags)
{
@@ -77,7 +87,15 @@
fd = open(line, O_NOCTTY | O_APPEND | O_WRONLY);
if (fd != -1)
{
- write(fd, buf, strlen(buf));
+ if (sigsetjmp(jmp, 1) == 0)
+ {
+ signal(SIGALRM, alarmproc);
+ alarm(15);
+ write(fd, buf, strlen(buf));
+ }
+
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
close(fd);
}
}