[syslog-ng] bug in syslog-ng 3.9.1 triggered by bug in ivykis >= 0.40

Lennert Buytenhek buytenh at wantstofly.org
Sat Apr 29 12:13:00 UTC 2017


On Wed, Apr 26, 2017 at 08:49:04PM +0300, Lennert Buytenhek wrote:

> A syslog-ng user tried to use syslog-ng with ivykis 0.41 and ran into
> the following issue:
> 
> 	https://github.com/buytenh/ivykis/issues/11
> 
> In a nutshell, syslog-ng seems to be registering an ivykis timer
> (iv_timer) with timeout tv_sec = 0, tv_nsec = 0, and ivykis >= 0.40
> added support for timerfd_create, but due to a bug in ivykis, this
> {0, 0} timeout would get passed into timerfd_settime() verbatim, and
> timerfd_settime() interprets this zero timeout as a request to disable
> the timerfd, which would cause timer processing to stop.
> 
> I will release a new ivykis release with a workaround for this, but I
> figured that you'd probably want to know about this as well, as I don't
> think it makes sense for syslog-ng to be registering timers with an
> absolute timeout of zero.

FWIW, I just released ivykis 0.42 with the commit below, which fixes
this issue.

(And sorry, no, I don't have a syslog-ng backtrace, so I have no idea
which code in syslog-ng is registering a timer with an expiry time of
zero. :-(  )



commit 580ea0f50c9ea1c537398bed1b1e3a861440c97f
Author: Lennert Buytenhek <buytenh at wantstofly.org>
Date:   Wed Apr 26 22:28:20 2017 +0300

    Fix ->set_poll_timeout() related bug with timers that expire at time zero.

    If the ivykis core decides to use ->set_poll_timeout() to offload the
    handling of a timer, the epoll_create(2) / port_create(3C) poll
    methods pass the given timeout directly into the timerfd_settime(2) /
    timer_settime(3C) system calls, but if an ivykis user has registered
    an iv_timer with an expiration time of (tv_sec, tv_nsec) = (0, 0),
    the *_settime() system calls will interpret such a zero timeout value
    as a request to disable the timer, and as a result, no timer handlers
    will be run.

    To work around this, we'll pass a timeout of (tv_sec, tv_nsec) = (0, 1)
    into these system calls if the next expiring timer expires at (0, 0).

    This bug was reported by and tracked down with the kind help of
    Brian De Wolf (github: bldewolf), who ran into this issue with
    syslog-ng 3.9.1.

    Signed-off-by: Lennert Buytenhek <buytenh at wantstofly.org>

diff --git a/src/iv_fd_epoll.c b/src/iv_fd_epoll.c
index 5517d19..c6b2285 100644
--- a/src/iv_fd_epoll.c
+++ b/src/iv_fd_epoll.c
@@ -388,6 +388,8 @@ iv_fd_epoll_timerfd_set_poll_timeout(struct iv_state *st,
        val.it_interval.tv_sec = 0;
        val.it_interval.tv_nsec = 0;
        val.it_value = *abs;
+       if (val.it_value.tv_sec == 0 && val.it_value.tv_nsec == 0)
+               val.it_value.tv_nsec = 1;
 
        ret = timerfd_settime(st->u.epoll.timer_fd,
                              TFD_TIMER_ABSTIME, &val, NULL);
diff --git a/src/iv_fd_port.c b/src/iv_fd_port.c
index 2d427b5..510c948 100644
--- a/src/iv_fd_port.c
+++ b/src/iv_fd_port.c
@@ -296,6 +296,8 @@ iv_fd_port_set_poll_timeout(struct iv_state *st, const struct timespec *abs)
        val.it_interval.tv_sec = 0;
        val.it_interval.tv_nsec = 0;
        val.it_value = *abs;
+       if (val.it_value.tv_sec == 0 && val.it_value.tv_nsec == 0)
+               val.it_value.tv_nsec = 1;
 
        ret = timer_settime(st->u.port.timer_id, TIMER_ABSTIME, &val, NULL);
        if (ret < 0) {


More information about the syslog-ng mailing list