Compare commits

..

3 Commits
rawhide ... f14

Author SHA1 Message Date
Jose Pedro Oliveira
8629f464db Patch for CVE-2011-1951: syslog-ng-3.1.4-pcre-dos.patch (#709088)
Enabled the test suite
2011-06-17 04:02:53 +01:00
Jose Pedro Oliveira
8108ce0d9d * Sync with EL6 branch 2011-05-09 22:11:10 +01:00
Jose Pedro Oliveira
f552242505 * Update to 3.1.4 2011-05-07 20:57:26 +01:00
10 changed files with 542 additions and 1009 deletions

48
.gitignore vendored
View File

@ -1,48 +1,2 @@
syslog-ng_3.1.1.tar.gz
/syslog-ng-3.2.2.tar.bz2
/syslog-ng-3.2.3-20110424.tar.bz2
/syslog-ng_3.2.3.tar.gz
/syslog-ng_3.2.4.tar.gz
/syslog-ng-3.2.4+20111022+0801.tar.gz
/syslog-ng-3.2.4+20111023+0856.tar.gz
/syslog-ng_3.2.5.tar.gz
/syslog-ng-3.3.6.91-20121008-v3.3.6.91.tar.gz
/syslog-ng_3.3.7.tar.gz
/syslog-ng_3.3.8.tar.gz
/syslog-ng_3.4.0rc2.tar.gz
/syslog-ng_3.4.1.tar.gz
/syslog-ng_3.4.3.tar.gz
/syslog-ng_3.4.4.tar.gz
/syslog-ng_3.5.0beta3.tar.gz
/syslog-ng_3.5.0rc1.tar.gz
/syslog-ng_3.5.1.tar.gz
/syslog-ng_3.5.2.tar.gz
/syslog-ng_3.5.3.tar.gz
/syslog-ng_3.5.4.1.tar.gz
/syslog-ng_3.5.5.tar.gz
/syslog-ng_3.5.6.tar.gz
/syslog-ng-3.6.0rc1.tar.gz
/syslog-ng_3.6.0rc1.tar.gz
/syslog-ng_3.6.1.tar.gz
/syslog-ng_3.6.2.tar.gz
/syslog-ng-3.8.1.tar.gz
/syslog-ng-3.9.1.tar.gz
/syslog-ng-3.10.1.tar.gz
/syslog-ng-3.11.1.tar.gz
/syslog-ng-3.14.1.tar.gz
/syslog-ng-3.15.1.tar.gz
/syslog-ng-3.16.1.tar.gz
/syslog-ng-3.17.1.tar.gz
/syslog-ng-3.17.2.tar.gz
/syslog-ng-3.18.1.tar.gz
/syslog-ng-3.19.1.tar.gz
/syslog-ng-3.20.1.tar.gz
/syslog-ng-3.21.1.tar.gz
/syslog-ng-3.22.1.tar.gz
/syslog-ng-3.23.1.tar.gz
/syslog-ng-3.25.1.tar.gz
/syslog-ng-3.27.1.tar.gz
/syslog-ng-3.30.1.tar.gz
/syslog-ng-3.33.2.tar.gz
/syslog-ng-3.35.1.tar.gz
/syslog-ng-3.37.1.tar.gz
/syslog-ng_3.1.4.tar.gz

View File

@ -1 +1 @@
SHA512 (syslog-ng-3.37.1.tar.gz) = beebd89c54a415469dc58630ac1900d632ef351f6a13fad4a95ce7bb1760b16d6cfdcede02225a35e97ebce7dae151c6aa228f3d378463e8b873c4f71ed86ab7
48e6646d12d30c655f4391b970d61f56 syslog-ng_3.1.4.tar.gz

View File

@ -0,0 +1,19 @@
diff -ruN syslog-ng-3.1.4/tests/functional/func_test.py syslog-ng-3.1.4-modified/tests/functional/func_test.py
--- syslog-ng-3.1.4/tests/functional/func_test.py 2009-11-21 15:48:09.000000000 +0000
+++ syslog-ng-3.1.4-modified/tests/functional/func_test.py 2011-06-17 03:44:18.057873606 +0100
@@ -60,11 +60,12 @@
# import test modules
import test_file_source
import test_filters
-import test_input_drivers
+#import test_input_drivers
import test_performance
-import test_sql
+#import test_sql
-tests = (test_input_drivers, test_sql, test_file_source, test_filters, test_performance)
+#tests = (test_input_drivers, test_sql, test_file_source, test_filters, test_performance)
+tests = (test_file_source, test_filters, test_performance)
init_env()
seed_rnd()

View File

@ -0,0 +1,271 @@
commit 35de55e53dd653c50c8da5daf41a99ab22e7e8aa
Author: Balazs Scheidler <bazsi@balabit.hu>
Date: Tue May 3 20:54:53 2011 +0200
pcre: fixed a potential resource hogging infinite loop when an error occurs
Any kind of PCRE error case would cause an infinite loop, when the
"global" flag is present and pcre returns an error code.
The reported problem is that with PCRE 8.12 we indeed get such an error
while doing a global replace.
This patch also reworks the way PCRE based replacements are made, that code
was hairy, and I just hope this one is one bit less so. One performance
related change also made it that improves the speed pcre replacements,
which previously zeroed out a 3k array unconditionally in every invocation.
Also added some additional testcases to be sure I didn't break anything.
Reported-By: Micah Anderson <micah@riseup.net>
Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
diff --git a/src/logmatcher.c b/src/logmatcher.c
index 67b6c1b..6b70f13 100644
--- a/src/logmatcher.c
+++ b/src/logmatcher.c
@@ -504,7 +504,6 @@ typedef struct _LogMatcherPcreRe
pcre *pattern;
pcre_extra *extra;
gint match_options;
- int start_offset;
} LogMatcherPcreRe;
static gboolean
@@ -623,29 +622,37 @@ static gboolean
log_matcher_pcre_re_match(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len)
{
LogMatcherPcreRe *self = (LogMatcherPcreRe *) s;
- int matches[RE_MAX_MATCHES * 3];
+ gint *matches;
+ gsize matches_size;
+ gint num_matches;
gint rc;
- if(value_len == -1)
+ if (value_len == -1)
value_len = strlen(value);
- self->start_offset = 0;
- rc = pcre_exec(self->pattern, self->extra, value, value_len, self->start_offset, self->match_options, matches, (RE_MAX_MATCHES * 3));
+ if (pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_CAPTURECOUNT, &num_matches) < 0)
+ g_assert_not_reached();
+ if (num_matches > RE_MAX_MATCHES)
+ num_matches = RE_MAX_MATCHES;
+
+ matches_size = 3 * (num_matches + 1);
+ matches = g_alloca(matches_size * sizeof(gint));
+
+ rc = pcre_exec(self->pattern, self->extra,
+ value, value_len, 0, self->match_options, matches, matches_size);
if (rc < 0)
{
switch (rc)
{
- case PCRE_ERROR_NOMATCH:
- /*
- msg_debug("No match", NULL);
- */
+ case PCRE_ERROR_NOMATCH:
break;
+
+ default:
/* Handle other special cases */
- default:
- msg_error("Error while matching regexp",
- evt_tag_int("error_code",rc),
- NULL);
- break;
+ msg_error("Error while matching regexp",
+ evt_tag_int("error_code", rc),
+ NULL);
+ break;
}
return FALSE;
}
@@ -668,78 +675,120 @@ static gchar *
log_matcher_pcre_re_replace(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len, LogTemplate *replacement, gssize *new_length)
{
LogMatcherPcreRe *self = (LogMatcherPcreRe *) s;
- int matches[RE_MAX_MATCHES * 3];
- gint rc;
- gboolean first_round = TRUE;
GString *new_value = NULL;
- gssize last_offset = 0;
- gint options = 0;
+ gint *matches;
+ gsize matches_size;
+ gint num_matches;
+ gint rc;
+ gint start_offset, last_offset;
+ gint options;
+ gboolean last_match_was_empty;
+
+ if (pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_CAPTURECOUNT, &num_matches) < 0)
+ g_assert_not_reached();
+ if (num_matches > RE_MAX_MATCHES)
+ num_matches = RE_MAX_MATCHES;
+
+ matches_size = 3 * (num_matches + 1);
+ matches = g_alloca(matches_size * sizeof(gint));
+
+ /* we need zero initialized offsets for the last match as the
+ * algorithm tries uses that as the base position */
- memset(matches, 0, sizeof(matches));
+ matches[0] = matches[1] = matches[2] = 0;
if (value_len == -1)
value_len = strlen(value);
+ last_offset = start_offset = 0;
+ last_match_was_empty = FALSE;
do
{
- options = 0;
- self->start_offset = matches[1]; /* Start at end of previous match 0 on the first iteration*/
-
- /* If the previous match was for an empty string, we are finished if we are
- at the end of the subject. Otherwise, arrange to run another match at the
- same point to see if a non-empty match can be found.
+ /* loop over the string, replacing one occurence at a time. */
+
+ /* NOTE: zero length matches need special care, as we could spin
+ * forever otherwise (since the current position wouldn't be
+ * advanced).
+ *
+ * A zero-length match can be as simple as "a*" which will be
+ * returned unless PCRE_NOTEMPTY is specified.
+ *
+ * By supporting zero-length matches, we basically make it
+ * possible to insert replacement between each incoming
+ * character.
+ *
+ * For example:
+ * pattern: a*
+ * replacement: #
+ * input: message
+ * result: #m#e#s#s#a#g#e#
+ *
+ * This mimics Perl behaviour.
*/
- if (matches[0] == matches[1] && !first_round)
+ if (last_match_was_empty)
{
- if (matches[0] == value_len)
- break;
+ /* Otherwise, arrange to run another match at the same point
+ * to see if a non-empty match can be found.
+ */
+
options = PCRE_NOTEMPTY | PCRE_ANCHORED;
}
+ else
+ {
+ options = 0;
+ }
- rc = pcre_exec(self->pattern, self->extra, value, value_len, self->start_offset/*start offset*/, (self->match_options | options) , matches, (RE_MAX_MATCHES * 3) );
- if (rc < 0)
+ rc = pcre_exec(self->pattern, self->extra,
+ value, value_len,
+ start_offset, (self->match_options | options), matches, matches_size);
+ if (rc < 0 && rc != PCRE_ERROR_NOMATCH)
{
- if(rc == PCRE_ERROR_NOMATCH)
- {
- /* msg_debug("No match", NULL); */
- if(!first_round)
- {
- if (options == 0)
- break;
- else
- matches[1] = self->start_offset + 1;
- continue; /* Go round the loop again */
- }
- }
- else
- {
- /* Handle other special cases */
- msg_error("Error while matching regexp",
- evt_tag_int("error_code",rc),
- NULL);
- }
+ msg_error("Error while matching regexp",
+ evt_tag_int("error_code", rc),
+ NULL);
+ break;
}
- else if (rc == 0)
+ else if (rc < 0)
{
- msg_error("Error while storing matching substrings", NULL);
+ if ((options & PCRE_NOTEMPTY) == 0)
+ {
+ /* we didn't match, even when we permitted to match the
+ * empty string. Nothing to find here, bail out */
+ break;
+ }
+
+ /* we didn't match, quite possibly because the empty match
+ * was not permitted. Skip one character in order to avoid
+ * infinite loop over the same zero-length match. */
+
+ start_offset = start_offset + 1;
+ /* FIXME: handle complex sequences like utf8 and newline characters */
+ last_match_was_empty = FALSE;
+ continue;
}
else
{
+ /* if the output array was too small, truncate the number of
+ captures to RE_MAX_MATCHES */
+
+ if (rc == 0)
+ rc = matches_size / 3;
+
log_matcher_pcre_re_feed_backrefs(s, msg, value_handle, matches, rc, value);
log_matcher_pcre_re_feed_named_substrings(s, msg, matches, value);
if (!new_value)
new_value = g_string_sized_new(value_len);
- /* literal */
+ /* append non-matching portion */
g_string_append_len(new_value, &value[last_offset], matches[0] - last_offset);
/* replacement */
log_template_append_format(replacement, msg, 0, TS_FMT_BSD, NULL, 0, 0, new_value);
- last_offset = matches[1];
+ last_match_was_empty = (matches[0] == matches[1]);
+ start_offset = last_offset = matches[1];
}
- first_round = FALSE;
}
- while (TRUE && (self->super.flags & LMF_GLOBAL));
+ while (self->super.flags & LMF_GLOBAL && start_offset < value_len);
if (new_value)
{
diff --git a/tests/unit/test_matcher.c b/tests/unit/test_matcher.c
index 3df98e5..95866b3 100644
--- a/tests/unit/test_matcher.c
+++ b/tests/unit/test_matcher.c
@@ -144,9 +144,18 @@ main()
/* empty match with global flag*/
testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa bb", 0, "c*", "#", "#a#a# #b#b#", LMF_GLOBAL, log_matcher_pcre_re_new());
testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa bb", 0, "a*", "?", "?? ?b?b?", LMF_GLOBAL, log_matcher_pcre_re_new());
+ testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa", 0, "aa|b*", "@", "@@", LMF_GLOBAL, log_matcher_pcre_re_new());
+ testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa", 0, "aa|b*", "@", "@", 0, log_matcher_pcre_re_new());
+ testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa", 0, "b*|aa", "@", "@@@", LMF_GLOBAL, log_matcher_pcre_re_new());
+ testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa", 0, "b*|aa", "@", "@aa", 0, log_matcher_pcre_re_new());
testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", 0, "wi", "", "kiki", LMF_GLOBAL, log_matcher_pcre_re_new());
testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", 0, "wi", "kuku", "kukukikukuki", LMF_GLOBAL, log_matcher_pcre_re_new());
+
+ /* this tests a pcre 8.12 incompatibility */
+
+ testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", 0, "([[:digit:]]{1,3}\\.){3}[[:digit:]]{1,3}", "foo", "wikiwiki", LMF_GLOBAL, log_matcher_pcre_re_new());
+
#endif
return 0;

View File

@ -1,5 +1,4 @@
@version: 3.35
@include "scl.conf"
@version:3.0
# syslog-ng configuration file.
#
@ -8,24 +7,23 @@
#
# See syslog-ng(8) and syslog-ng.conf(5) for more information.
#
# Note: it also sources additional configuration files (*.conf)
# located in /etc/syslog-ng/conf.d/
options {
flush_lines (0);
time_reopen (10);
log_fifo_size (1000);
chain_hostnames (off);
use_dns (no);
use_fqdn (no);
create_dirs (no);
keep_hostname (yes);
flush_lines (0);
time_reopen (10);
log_fifo_size (1000);
long_hostnames (off);
use_dns (no);
use_fqdn (no);
create_dirs (no);
keep_hostname (yes);
};
source s_sys {
system();
internal();
# udp(ip(0.0.0.0) port(514));
file ("/proc/kmsg" program_override("kernel: "));
unix-stream ("/dev/log");
internal();
# udp(ip(0.0.0.0) port(514));
};
destination d_cons { file("/dev/console"); };
@ -62,9 +60,4 @@ log { source(s_sys); filter(f_news); destination(d_spol); };
log { source(s_sys); filter(f_boot); destination(d_boot); };
log { source(s_sys); filter(f_cron); destination(d_cron); };
# Source additional configuration files (.conf extension only)
@include "/etc/syslog-ng/conf.d/*.conf"
# vim:ft=syslog-ng:ai:si:ts=4:sw=4:et:

123
syslog-ng.init.d Normal file
View File

@ -0,0 +1,123 @@
#!/bin/sh
#
# syslog-ng starts/stops syslog-ng service
#
# chkconfig: - 12 88
# description: Syslog is the facility by which many daemons use to log \
# messages to various system log files.
#
### BEGIN INIT INFO
# Provides: $syslog
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Short-Description: Next-generation syslog server
# Description: syslog-ng, as the name shows, is a syslogd replacement, but
# with new functionality for the new generation. The original syslogd
# allows messages only to be sorted based on priority/facility pairs;
# syslog-ng adds the possibility to filter based on message contents
# using regular expressions. The new configuration scheme is intuitive
# and powerful. Forwarding logs over TCP and remembering all forwarding
# hops makes it ideal for firewalled environments.
### END INIT INFO
# Source function library.
. /etc/init.d/functions
[ -e /etc/sysconfig/syslog-ng ] && . /etc/sysconfig/syslog-ng
RETVAL=0
check_syntax()
{
[ -x /sbin/syslog-ng ] || exit 5
syslog-ng -s $SYSLOGNG_OPTIONS
RETVAL=$?
return $RETVAL
}
verify_config()
{
check_syntax
RETVAL=$?
[ $RETVAL -eq 0 ] || exit $retval
}
checkconfig()
{
action $"Checking Configuration: " check_syntax
}
start()
{
verify_config
echo -n $"Starting syslog-ng: "
if [ -e $SYSLOGNG_COMPAT_PID ]; then
failure "PID file for existing syslog daemon exists"
fi
daemon syslog-ng $SYSLOGNG_OPTIONS
ln -sf $SYSLOGNG_PID $SYSLOGNG_COMPAT_PID
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/syslog-ng
return $RETVAL
}
stop()
{
echo -n $"Stopping syslog-ng: "
REMOVE_COMPAT_PID=0
if [ -e $SYSLOGNG_PID ]; then
if [ -e $SYSLOGNG_COMPAT_PID -a $(<$SYSLOGNG_PID) == $(<$SYSLOGNG_COMPAT_PID) ]; then
REMOVE_COMPAT_PID=1
fi
fi
killproc syslog-ng
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/syslog-ng
[ $RETVAL -eq 0 -a $REMOVE_COMPAT_PID -eq 1 ] && rm -f $SYSLOGNG_COMPAT_PID
return $RETVAL
}
reload()
{
verify_config
echo -n $"Reloading syslog-ng: "
killproc syslog-ng -HUP
RETVAL=$?
echo
return $RETVAL
}
restart()
{
stop
start
}
case "$1" in
start|stop|reload)
$1
;;
restart|force_reload)
restart
;;
status)
status syslog-ng
;;
checkconfig|configtest|check|test)
checkconfig
;;
condrestart|try-restart)
[ -f /var/lock/subsys/syslog-ng ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|restart|reload|condrestart|checkconfig}"
exit 1
esac
exit $?
# vim: ft=sh:ts=4:ai:si:

View File

@ -1,9 +1,4 @@
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
/var/log/messages /var/log/secure /var/log/maillog /var/log/spooler /var/log/boot.log /var/log/cron {
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true

View File

@ -1,16 +0,0 @@
[Unit]
Description=System Logger Daemon
Documentation=man:syslog-ng(8)
[Service]
Type=notify
ExecStart=/usr/sbin/syslog-ng -F $SYSLOGNG_OPTS -p /var/run/syslogd.pid
ExecReload=/bin/kill -HUP $MAINPID
EnvironmentFile=-/etc/default/syslog-ng
EnvironmentFile=-/etc/sysconfig/syslog-ng
StandardOutput=journal
StandardError=journal
Restart=on-failure
[Install]
WantedBy=multi-user.target

File diff suppressed because it is too large Load Diff

3
syslog-ng.sysconfig Normal file
View File

@ -0,0 +1,3 @@
SYSLOGNG_PID="/var/run/syslog-ng.pid"
SYSLOGNG_OPTIONS="-p $SYSLOGNG_PID"
SYSLOGNG_COMPAT_PID="/var/run/syslogd.pid"