syslog-ng 2.0.x bug - facility(auth) fails to match any messages
I posted the message below a couple of weeks ago and did not get a response from anyone. Can anyone else confirm that this configuration fails to match the facility(auth) fails to match messages with a facility of auth? Balazs - can you make a comment on why this happens? Evan. -------- Original Message -------- Date: Wed, 28 Mar 2007 13:19:27 -0700 From: Evan Rempel <erempel@uvic.ca> Subject: 2.0.x bug - filter(auth) fails to match With the following configuration source local { unix-stream("/dev/log" max-connections(200)); file("/proc/kmsg" log_prefix("kernel: ")); internal(); }; template standard_file { template("$ISODATE $FULLHOST $FACILITY.$LEVEL $PRI $MESSAGE\n"); template_escape(no); }; destination auth.log { file("/var/syslog/auth.log.$YEAR$MONTH$DAY.000000" perm(0640) template(standard_file) ); }; destination unknown.log { file("/var/syslog/unknown.log.$YEAR$MONTH$DAY.000000" perm(0640) template(standard_file) ); }; destination test.log { file("/var/syslog/test.log.$YEAR$MONTH$DAY.000000" perm(0640) template(standard_file) ); }; filter f_auth { facility(auth); }; filter f_local1 { facility(local1); }; filter f_ldap { program(^slapd); }; # ****** PROBLEM LOG LINE **** log { source(local); filter(f_local1); filter(f_ldap); destination(test.log); }; # ****** PROBLEM LOG LINE **** log { source(local); filter(f_auth); destination(auth.log); }; # safegaurd to catch anything missed by other filters log { source(local); destination(unknown.log); flags(fallback); }; all of the log messages with the facility of auth go into the unknown.log file. If I remove the problematic log line (to test.log) or change the order of its filters or change the first filter to be other than f_local1 (even changing the f_local1 filter to match a different facility) then everything works as expected. All of these work fine # ------------- use other than filter f_local1 filter f_auth { facility(auth); }; filter f_local1 { facility(local1); }; filter f_ldap { program(slapd); }; log { source(local); filter(f_auth); filter(f_ldap); destination(test.log); }; # ------------ comment out the log line filter f_auth { facility(auth); }; filter f_local1 { facility(local1); }; filter f_ldap { program(slapd); }; # log { source(local); filter(f_local1); filter(f_ldap); destination(test.log); }; # ------------------ match facility local0 in the f_local1 filter filter f_auth { facility(auth); }; filter f_local1 { facility(local0); }; filter f_ldap { program(^slapd); }; log { source(local); filter(f_local1); filter(f_ldap); destination(test.log); }; # ----------------- make a more complex single filter rather than multiple filter item in the log line filter f_auth { facility(auth); }; filter f_local1 { facility(local1); }; filter f_ldap { program(^slapd); }; filter f_test { facility(local1) and program(^sldapd); }; log { source(local); filter(f_test); destination(test.log); }; So, how is the first example going wrong? Evan.
On Fri, 2007-04-13 at 22:11 -0700, Evan Rempel wrote:
I posted the message below a couple of weeks ago and did not get a response from anyone.
Can anyone else confirm that this configuration fails to match the facility(auth) fails to match messages with a facility of auth?
Balazs - can you make a comment on why this happens?
You usually get better answers if you try to minimize the information posted. You have a quite complicated configuration and this makes it difficult to reproduce the problem (if there's one involved). I have one tip though, do you recognize that multiple filter clauses in a log statement are ANDed and not ORed? This means that:
filter f_auth { facility(auth); }; filter f_local1 { facility(local1); }; filter f_ldap { program(^slapd); };
# ****** PROBLEM LOG LINE **** log { source(local); filter(f_local1); filter(f_ldap); destination(test.log); };
Test.log will only receive a message if the facility is local1 and the program sending the message is slapd. I've googled for this and slapd uses local4 by default: -l syslog-local-user Selects the local user of the syslog(8) facility. Values can be LOCAL0, LOCAL1, and so on, up to LOCAL7. The default is LOCAL4. However, this option is only permitted on systems that support local users with the syslog(8) facility. -- Bazsi
Balazs Scheidler wrote:
You usually get better answers if you try to minimize the information posted. You have a quite complicated configuration and this makes it difficult to reproduce the problem (if there's one involved).
Yes, thank you. I tried to get the problem as simple as I could. Our actual configuration is a LOT more complicated.
I have one tip though, do you recognize that multiple filter clauses in a log statement are ANDed and not ORed?
Yes, I do realize this. If I make a single filter of filter f_single{ facility(local1) and program(^sldapd); }; and use filter rather than using two filters in the log line, things work as documented. The problem is with messages that should match the facility of auth not with the messages that match local1 and ldap.
This means that:
filter f_auth { facility(auth); }; filter f_local1 { facility(local1); }; filter f_ldap { program(^slapd); };
# ****** PROBLEM LOG LINE **** log { source(local); filter(f_local1); filter(f_ldap); destination(test.log); };
Test.log will only receive a message if the facility is local1 and the program sending the message is slapd. I've googled for this and slapd uses local4 by default:
Yes, in our environment our primary LDAP server logs with the facility of local1. It is easy to test. Use the attached configuration and try to log with any priority auth.* and see where the messages get logged. They should be logged in the auth.log but on my system they are logged into unknown.log Evan. source local { unix-stream("/dev/log" max-connections(200)); file("/proc/kmsg" log_prefix("kernel: ")); internal(); }; template standard_file { template("$ISODATE $FULLHOST $FACILITY.$LEVEL $PRI $MESSAGE\n"); template_escape(no); }; destination auth.log { file("/var/syslog/auth.log.$YEAR$MONTH$DAY.000000" perm(0640) template(standard_file) ); }; destination unknown.log { file("/var/syslog/unknown.log.$YEAR$MONTH$DAY.000000" perm(0640) template(standard_file) ); }; destination test.log { file("/var/syslog/test.log.$YEAR$MONTH$DAY.000000" perm(0640) template(standard_file) ); }; filter f_auth { facility(auth); }; filter f_local1 { facility(local1); }; filter f_ldap { program(^slapd); }; # ****** PROBLEM LOG LINE **** log { source(local); filter(f_local1); filter(f_ldap); destination(test.log); }; # ****** PROBLEM LOG LINE **** log { source(local); filter(f_auth); destination(auth.log); }; # safegaurd to catch anything missed by other filters log { source(local); destination(unknown.log); flags(fallback); };
On Mon, 2007-04-16 at 10:33 -0700, Evan Rempel wrote:
Balazs Scheidler wrote:
and use filter rather than using two filters in the log line, things work as documented.
The problem is with messages that should match the facility of auth not with the messages that match local1 and ldap.
This means that:
filter f_auth { facility(auth); }; filter f_local1 { facility(local1); }; filter f_ldap { program(^slapd); };
# ****** PROBLEM LOG LINE **** log { source(local); filter(f_local1); filter(f_ldap); destination(test.log); };
Test.log will only receive a message if the facility is local1 and the program sending the message is slapd. I've googled for this and slapd uses local4 by default:
Yes, in our environment our primary LDAP server logs with the facility of local1.
It is easy to test. Use the attached configuration and try to log with any priority auth.* and see where the messages get logged. They should be logged in the auth.log but on my system they are logged into unknown.log
Sorry for not responding for so long. The problem you reported was was indeed a bug in syslog-ng. The patch below fixes the problem in the code and adjusts the unit testcase to detect the problem. As a side-note, I've migrated to use git instead of GNU arch, thus daily snapshots will not receive this and further updates until I fix that to use my git tree instead. So you need to apply this patch by hand. Please give me some time to fix the snapshot generation. I'll try to publish my git tree in the interim time. diff --git a/src/filter.c b/src/filter.c index 04e3639..269d016 100644 --- a/src/filter.c +++ b/src/filter.c @@ -208,7 +208,7 @@ filter_facility_eval(FilterExprNode *s, LogMessage *msg) { if (sl_facilities[i].value == fac) { - if (fac_num < 32) + if (fac_num < 32 && bitpos[fac_num] == -1) bitpos[fac_num] = i; if (bits & 1) { diff --git a/tests/unit/test_filters.c b/tests/unit/test_filters.c index 422dff2..58236d7 100644 --- a/tests/unit/test_filters.c +++ b/tests/unit/test_filters.c @@ -91,6 +91,7 @@ main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) testcase("<128> openvpn[2499]: PTHREAD support initialized", 0, filter_facility_new(facility_bits("local0")), 1); testcase("<128> openvpn[2499]: PTHREAD support initialized", 0, filter_facility_new(0x80000000 | (LOG_LOCAL0 >> 3)), 1); + testcase("<32> openvpn[2499]: PTHREAD support initialized", 0, filter_facility_new(facility_bits("local1")), 0); testcase("<32> openvpn[2499]: PTHREAD support initialized", 0, filter_facility_new(facility_bits("auth")), 1); testcase("<32> openvpn[2499]: PTHREAD support initialized", 0, filter_facility_new(0x80000000 | (LOG_AUTH >> 3)), 1); testcase("<80> openvpn[2499]: PTHREAD support initialized", 0, filter_facility_new(facility_bits("authpriv")), 1); -- Bazsi
On Fri, 2007-04-20 at 20:23 +0000, Balazs Scheidler wrote:
On Mon, 2007-04-16 at 10:33 -0700, Evan Rempel wrote:
Balazs Scheidler wrote:
and use filter rather than using two filters in the log line, things work as documented.
The problem is with messages that should match the facility of auth not with the messages that match local1 and ldap.
This means that:
filter f_auth { facility(auth); }; filter f_local1 { facility(local1); }; filter f_ldap { program(^slapd); };
# ****** PROBLEM LOG LINE **** log { source(local); filter(f_local1); filter(f_ldap); destination(test.log); };
Test.log will only receive a message if the facility is local1 and the program sending the message is slapd. I've googled for this and slapd uses local4 by default:
Yes, in our environment our primary LDAP server logs with the facility of local1.
It is easy to test. Use the attached configuration and try to log with any priority auth.* and see where the messages get logged. They should be logged in the auth.log but on my system they are logged into unknown.log
Sorry for not responding for so long. The problem you reported was was indeed a bug in syslog-ng. The patch below fixes the problem in the code and adjusts the unit testcase to detect the problem.
As a side-note, I've migrated to use git instead of GNU arch, thus daily snapshots will not receive this and further updates until I fix that to use my git tree instead. So you need to apply this patch by hand.
Please give me some time to fix the snapshot generation. I'll try to publish my git tree in the interim time.
diff --git a/src/filter.c b/src/filter.c index 04e3639..269d016 100644 --- a/src/filter.c +++ b/src/filter.c
this patch is crap, it fixes the specific problem, but may not cover another case. Here's a better version instead. diff --git a/src/cfg-grammar.y b/src/cfg-grammar.y index 6f5cfe1..af729fd 100644 --- a/src/cfg-grammar.y +++ b/src/cfg-grammar.y @@ -808,7 +808,7 @@ filter_simple_expr ; filter_fac_list - : filter_fac filter_fac_list { $$ = $1 + $2; } + : filter_fac filter_fac_list { $$ = $1 | $2; } | filter_fac { $$ = $1; } ; @@ -830,7 +830,7 @@ filter_fac ; filter_level_list - : filter_level filter_level_list { $$ = $1 + $2; } + : filter_level filter_level_list { $$ = $1 | $2; } | filter_level { $$ = $1; } ; diff --git a/src/filter.c b/src/filter.c index 04e3639..8e19440 100644 --- a/src/filter.c +++ b/src/filter.c @@ -178,45 +178,16 @@ static gboolean filter_facility_eval(FilterExprNode *s, LogMessage *msg) { FilterPri *self = (FilterPri *) s; - guint32 fac = msg->pri & LOG_FACMASK, fac_num = (msg->pri & LOG_FACMASK) >> 3; - guint32 bits = self->valid; - int i; + guint32 fac_num = (msg->pri & LOG_FACMASK) >> 3; - if (G_UNLIKELY(bits & 0x80000000)) + if (G_UNLIKELY(self->valid & 0x80000000)) { /* exact number specified */ - return ((bits & ~0x80000000) == fac_num) ^ s->comp; + return ((self->valid & ~0x80000000) == fac_num) ^ s->comp; } else { - static gint8 bitpos[32] = - { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 - }; - - if (G_LIKELY(fac_num < 32 && bitpos[fac_num] != -1)) - { - if (self->valid & (1 << bitpos[fac_num])) - return !self->super.comp; - } - else - { - for (i = 0; bits && sl_facilities[i].name; i++, bits >>= 1) - { - if (sl_facilities[i].value == fac) - { - if (fac_num < 32) - bitpos[fac_num] = i; - if (bits & 1) - { - return !self->super.comp; - } - } - } - } + return !!(self->valid & (1 << fac_num)) ^ self->super.comp; } return self->super.comp; } diff --git a/src/syslog-names.h b/src/syslog-names.h index 5afc924..40e8b4f 100644 --- a/src/syslog-names.h +++ b/src/syslog-names.h @@ -43,7 +43,21 @@ const char *syslog_name_lookup_name_by_value(int value, struct sl_name names[]); guint32 syslog_make_range(guint32 r1, guint32 r2); -#define syslog_name_lookup_level_by_name(name) syslog_name_lookup_value_by_name(name, sl_levels) -#define syslog_name_lookup_facility_by_name(name) syslog_name_lookup_id_by_name(name, sl_facilities) +static inline guint32 +syslog_name_lookup_level_by_name(const gchar *name) +{ + return syslog_name_lookup_value_by_name(name, sl_levels); +} + +static inline guint32 +syslog_name_lookup_facility_by_name(const gchar *name) +{ + guint32 res; + + res = syslog_name_lookup_value_by_name(name, sl_facilities); + if (res != -1) + return res >> 3; + return res; +} #endif -- Bazsi
participants (2)
-
Balazs Scheidler
-
Evan Rempel