Date: Tuesday, February 14, 2017 @ 23:23:47 Author: seblu Revision: 288997
archrelease: copy trunk to staging-i686, staging-x86_64 Added: ulogd/repos/staging-i686/ ulogd/repos/staging-i686/01-fix-FS#48318.patch (from rev 288996, ulogd/trunk/01-fix-FS#48318.patch) ulogd/repos/staging-i686/PKGBUILD (from rev 288996, ulogd/trunk/PKGBUILD) ulogd/repos/staging-i686/ulogd.conf (from rev 288996, ulogd/trunk/ulogd.conf) ulogd/repos/staging-i686/ulogd.logrotate (from rev 288996, ulogd/trunk/ulogd.logrotate) ulogd/repos/staging-i686/ulogd.service (from rev 288996, ulogd/trunk/ulogd.service) ulogd/repos/staging-x86_64/ ulogd/repos/staging-x86_64/01-fix-FS#48318.patch (from rev 288996, ulogd/trunk/01-fix-FS#48318.patch) ulogd/repos/staging-x86_64/PKGBUILD (from rev 288996, ulogd/trunk/PKGBUILD) ulogd/repos/staging-x86_64/ulogd.conf (from rev 288996, ulogd/trunk/ulogd.conf) ulogd/repos/staging-x86_64/ulogd.logrotate (from rev 288996, ulogd/trunk/ulogd.logrotate) ulogd/repos/staging-x86_64/ulogd.service (from rev 288996, ulogd/trunk/ulogd.service) --------------------------------------+ staging-i686/01-fix-FS#48318.patch | 312 +++++++++++++++++++++++++++++++++ staging-i686/PKGBUILD | 82 ++++++++ staging-i686/ulogd.conf | 20 ++ staging-i686/ulogd.logrotate | 10 + staging-i686/ulogd.service | 11 + staging-x86_64/01-fix-FS#48318.patch | 312 +++++++++++++++++++++++++++++++++ staging-x86_64/PKGBUILD | 82 ++++++++ staging-x86_64/ulogd.conf | 20 ++ staging-x86_64/ulogd.logrotate | 10 + staging-x86_64/ulogd.service | 11 + 10 files changed, 870 insertions(+) Copied: ulogd/repos/staging-i686/01-fix-FS#48318.patch (from rev 288996, ulogd/trunk/01-fix-FS#48318.patch) =================================================================== --- staging-i686/01-fix-FS#48318.patch (rev 0) +++ staging-i686/01-fix-FS#48318.patch 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,312 @@ +From 1f70d2ba45e2b067777d5386b8d3f2e09be9118b Mon Sep 17 00:00:00 2001 +From: Hironobu Ishii <ishii.hiron...@jp.fujitsu.com> +Date: Tue, 2 Feb 2016 23:01:41 +0900 +Subject: ulogd: restructures signal handling by self-pipe trick + +ulogd had a critical bug that is calling Async-Signal-Unsafe functions +in signal hander context. + - Most of libc functions like fopen(), malloc() are Async-Signal-Unsafe. + So you should not call these functions in signal handler context. + - Calling pluginstances in signal handler context is danger. + For implementer of pluginstances, it is very hard to recognize their + functions are called in signal handler context. + +To solve the issue, I restructured signal handling by self-pipe trick. +For more detail on self-pipe trick, please see the following. +https://lwn.net/Articles/177897/ + +This patch will solve various symptoms like following. + - Deadlock + - Segmentation fault caused by libc management data corruption, + - Other unpredictable behavior. + +Deadlock example +================ +This bug was already filed at: +https://bugzilla.netfilter.org/show_bug.cgi?id=1030 + +I also hit this bug. The backtrace of this issue is following. +In this case, main thread was calling ctime(), +and signal handler called localtime_r(). +That caused the dead lock while getting tzset_lock in __tz_convert(). +Because vsyslog() is Async-Signal-Unsafe function, we cannot call +this function in signal handler context. + + (gdb) bt + #0 __lll_lock_wait_private () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95 + #1 0x00007f3c3fc7e4ac in _L_lock_2462 () at tzset.c:621 + #2 0x00007f3c3fc7e2e7 in __tz_convert (timer=0x7f3c3ff8bf00 <tzset_lock>, + timer@entry=0x7fffcfa923b8, use_localtime=use_localtime@entry=1, + tp=tp@entry=0x7fffcfa92400) at tzset.c:624 + #3 0x00007f3c3fc7c28d in __localtime_r (t=t@entry=0x7fffcfa923b8, + tp=tp@entry=0x7fffcfa92400) at localtime.c:32 + #4 0x00007f3c3fcbf1ba in __GI___vsyslog_chk (pri=<optimized out>, flag=1, + fmt=0x406fa8 "signal received, calling pluginstances\n", ap=0x7fffcfa924a0) + at ../misc/syslog.c:199 + #5 0x00000000004037b5 in __ulogd_log () + #6 0x00000000004047be in signal_handler () + #7 <signal handler called> + #8 0x00007f3c3fcb62f5 in __GI___xstat (vers=<optimized out>, + name=0x7f3c3fd4b2c3 "/etc/localtime", buf=0x7fffcfa92c10) + at ../sysdeps/unix/sysv/linux/wordsize-64/xstat.c:37 + #9 0x00007f3c3fc7e5f6 in __tzfile_read (file=file@entry=0x7f3c3fd4b2c3 "/etc/localtime", + extra=extra@entry=0, extrap=extrap@entry=0x0) at tzfile.c:170 + #10 0x00007f3c3fc7d954 in tzset_internal (always=<optimized out>, + explicit=explicit@entry=1) at tzset.c:444 + #11 0x00007f3c3fc7e303 in __tz_convert (timer=0x7fffcfa92d50, + use_localtime=use_localtime@entry=1, tp=tp@entry=0x7f3c3ff8ed80 <_tmbuf>) + at tzset.c:629 + #12 0x00007f3c3fc7c2a1 in __GI_localtime (t=<optimized out>) at localtime.c:42 + #13 0x00007f3c3fc7c1f9 in ctime (t=<optimized out>) at ctime.c:27 + #14 0x00007f3c3e180ec2 in ?? () + #15 0x0000000056a100c2 in ?? () + #16 0xf8570f79d4fc4200 in ?? () + #17 0x000000000209bec0 in ?? () + #18 0x00007f3c4059f1f8 in ?? () + #19 0x000000000000003c in ?? () + #20 0x0000000000404952 in ulogd_propagate_results () + #21 0x00007f3c3f9cc203 in ?? () + #22 0x0000000000000000 in ?? () + +Segmentation fault in free() +============================ +>From my experience, I think this was caused by some routine called +malloc()/free() in signal handler context. +By that, malloc() management data became inconsistent. +As a result, free() made a wrong dereference. + +Program terminated with signal SIGSEGV, Segmentation fault. + #0 __GI___libc_free (mem=0x7f430f011000) at malloc.c:2903 + 2903 if (chunk_is_mmapped(p)) /* release mmapped memory. */ + (gdb) bt + #0 __GI___libc_free (mem=0x7f430f011000) at malloc.c:2903 + #1 0x00007f430e68affa in __GI__IO_free_backup_area (fp=fp@entry=0x742500) + at genops.c:210 + #2 0x00007f430e68a795 in _IO_new_file_overflow (f=0x742500, ch=-1) at fileops.c:849 + #3 0x00007f430e689511 in _IO_new_file_xsputn (f=0x742500, data=<optimized out>, n=15) + at fileops.c:1372 + #4 0x00007f430e65aa4d in _IO_vfprintf_internal (s=s@entry=0x742500, + format=<optimized out>, format@entry=0x7f430cbc4008 "%.15s %s %s", + ap=ap@entry=0x7fff456ece38) at vfprintf.c:1635 + #5 0x00007f430e71d615 in ___fprintf_chk (fp=0x742500, flag=flag@entry=1, + format=format@entry=0x7f430cbc4008 "%.15s %s %s") at fprintf_chk.c:36 + #6 0x00007f430cbc3f04 in fprintf (__fmt=0x7f430cbc4008 "%.15s %s %s", + __stream=<optimized out>) at /usr/include/bits/stdio2.h:97 + #7 _output_logemu (upi=0x74e5a0) at ulogd_output_LOGEMU.c:102 + #8 0x0000000000404952 in ulogd_propagate_results () + #9 0x00007f430e40f203 in interp_packet (ldata=0x7fff456ed060, pf_family=2 '\002', + upi=0x74a6b0) at ulogd_inppkt_NFLOG.c:400 + #10 msg_cb (gh=<optimized out>, nfmsg=0x7f430efe2020, nfa=0x7fff456ed060, data=0x74a6b0) + at ulogd_inppkt_NFLOG.c:483 + #11 0x00007f430e20a307 in __nflog_rcv_pkt (nlh=<optimized out>, nfa=<optimized out>, + data=<optimized out>) at libnetfilter_log.c:160 + #12 0x00007f430e0056b7 in __nfnl_handle_msg (len=268, nlh=0x7f430efe2010, h=0x74e8e0) + at libnfnetlink.c:1236 + #13 nfnl_handle_packet (h=0x74e8e0, buf=0x7f430efe2010 "\f\001", len=<optimized out>) + at libnfnetlink.c:1256 + #14 0x00007f430e20a508 in nflog_handle_packet (h=<optimized out>, buf=<optimized out>, + len=<optimized out>) at libnetfilter_log.c:323 + #15 0x00007f430e40eaed in nful_read_cb (fd=<optimized out>, what=<optimized out>, + param=0x74a6b0) at ulogd_inppkt_NFLOG.c:463 + #16 0x0000000000404ee0 in ulogd_select_main () + #17 0x0000000000402b17 in main () + +Signed-off-by: Hironobu Ishii <ishii.hiron...@jp.fujitsu.com> +--- + src/ulogd.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 125 insertions(+), 7 deletions(-) + +diff --git a/src/ulogd.c b/src/ulogd.c +index 958c30a..c8d9376 100644 +--- a/src/ulogd.c ++++ b/src/ulogd.c +@@ -90,6 +90,29 @@ static int info_mode = 0; + static int verbose = 0; + static int created_pidfile = 0; + ++/* ++ * Using self-pipe trick to handle signals safely. ++ * (To avoid calling Async-Signal-Unsafe functions in signal handler.) ++ * ++ * cf. https://lwn.net/Articles/177897/ ++ * ++ * Capacity of pipe(2) buffer is >= 4096. ++ */ ++static int signal_channel[2] = { -1, -1 }; /* initialize with invalid fd */ ++#define SIGNAL_RX_FD (signal_channel[0]) /* main thread select() this fd */ ++#define SIGNAL_TX_FD (signal_channel[1]) /* signal handler writes to this fd */ ++ ++static void signal_handler(int signal); ++static void sigterm_handler_task(int signal); ++static void signal_handler_task(int signal); ++ ++static int signal_channel_callback(int fd, unsigned int what, void *data); ++static struct ulogd_fd signal_channel_ulogfd = { ++ .when = ULOGD_FD_READ, ++ .cb = &signal_channel_callback, ++ .data = &signal_channel_ulogfd, ++}; ++ + /* linked list for all registered plugins */ + static LLIST_HEAD(ulogd_plugins); + /* linked list for all plugins handle */ +@@ -387,6 +410,80 @@ void ulogd_register_plugin(struct ulogd_plugin *me) + } + + /*********************************************************************** ++ * UTILITY FUNCTIONS FOR SIGNAL HANDLING ++ ***********************************************************************/ ++static void call_signal_handler_tasks(int sig) ++{ ++ /* Deliver signals */ ++ switch (sig) { ++ case SIGTERM: ++ case SIGINT: ++ sigterm_handler_task(sig); ++ break; ++ case SIGHUP: ++ case SIGALRM: ++ case SIGUSR1: ++ case SIGUSR2: ++ signal_handler_task(sig); ++ break; ++ default: ++ break; ++ } ++} ++ ++static int signal_channel_callback(int fd, unsigned int what, void *data) ++{ ++ int ret; ++ unsigned char c; ++ ++ while ((ret = read(fd, &c, 1)) > 0) { ++ call_signal_handler_tasks((int)c); ++ } ++ return 0; ++} ++ ++static int create_signal_channel(void) ++{ ++ int ret; ++ long flags; ++ ++ if ((ret = pipe(signal_channel)) < 0) ++ return ret; ++ ++ /* SIGNAL_RX_FD, channel[0] */ ++ if ((flags = fcntl(SIGNAL_RX_FD, F_GETFL)) < 0) ++ goto err_exit; ++ flags |= O_NONBLOCK; ++ if ( fcntl(SIGNAL_RX_FD, F_SETFL, flags) < 0 ) ++ goto err_exit; ++ ++ /* SIGNAL_TX_FD, channel[1] */ ++ if ((flags = fcntl(SIGNAL_TX_FD, F_GETFL)) < 0) ++ goto err_exit; ++ flags |= O_NONBLOCK; ++ if ( fcntl(SIGNAL_TX_FD, F_SETFL, flags) < 0 ) ++ goto err_exit; ++ ++ /* register SIGNAL_RX_FD to ulogd */ ++ signal_channel_ulogfd.fd = SIGNAL_RX_FD; ++ ulogd_register_fd(&signal_channel_ulogfd); ++ ++ return 0; ++ ++err_exit: ++ if (SIGNAL_RX_FD >= 0) { ++ (void)close(SIGNAL_RX_FD); ++ SIGNAL_RX_FD = -1; ++ } ++ if (SIGNAL_TX_FD >= 0) { ++ (void)close(SIGNAL_TX_FD); ++ SIGNAL_TX_FD = -1; ++ } ++ return -1; ++} ++ ++ ++/*********************************************************************** + * MAIN PROGRAM + ***********************************************************************/ + +@@ -925,7 +1022,6 @@ static void ulogd_main_loop(void) + struct timeval *next = NULL; + + while (1) { +- /* XXX: signal blocking? */ + if (next != NULL && !timerisset(next)) + next = ulogd_do_timer_run(&next_alarm); + else +@@ -1225,7 +1321,19 @@ static void stop_stack() + } + + +-static void sigterm_handler(int signal) ++/* This is a real SIGTERM, SIGINT, SIGHUP, SIGALRM, SIGUSR1, SIGUSR2 handler */ ++static void signal_handler(int signal) ++{ ++ unsigned char c = (unsigned char)signal; ++ ++ (void)write(SIGNAL_TX_FD, &c, 1); ++} ++ ++/* This is NOT a real signal handler. ++ * It is called in ulogd_main_loop() to avoid ++ * calling Async-Signal-UnSafe functions in signal handler. ++ */ ++static void sigterm_handler_task(int signal) + { + + ulogd_log(ULOGD_NOTICE, "Terminal signal received, exiting\n"); +@@ -1255,7 +1363,12 @@ static void sigterm_handler(int signal) + exit(0); + } + +-static void signal_handler(int signal) ++ ++/* This is NOT a real signal handler. ++ * It is called in ulogd_main_loop() to avoid ++ * calling Async-Signal-UnSafe functions in signal handler. ++ */ ++static void signal_handler_task(int signal) + { + ulogd_log(ULOGD_NOTICE, "signal received, calling pluginstances\n"); + +@@ -1269,7 +1382,7 @@ static void signal_handler(int signal) + fprintf(stderr, + "ERROR: can't open logfile %s: %s\n", + ulogd_logfile, strerror(errno)); +- sigterm_handler(signal); ++ sigterm_handler_task(signal); + } + + } +@@ -1464,8 +1577,13 @@ int main(int argc, char* argv[]) + } + } + +- signal(SIGTERM, &sigterm_handler); +- signal(SIGINT, &sigterm_handler); ++ if (create_signal_channel() < 0) { ++ ulogd_log(ULOGD_FATAL, "can't create signal channel\n"); ++ warn_and_exit(daemonize); ++ } ++ ++ signal(SIGTERM, &signal_handler); ++ signal(SIGINT, &signal_handler); + signal(SIGHUP, &signal_handler); + signal(SIGALRM, &signal_handler); + signal(SIGUSR1, &signal_handler); +@@ -1477,6 +1595,6 @@ int main(int argc, char* argv[]) + ulogd_main_loop(); + + /* hackish, but result is the same */ +- sigterm_handler(SIGTERM); ++ sigterm_handler_task(SIGTERM); + return(0); + } +-- +cgit v0.11.2 + Copied: ulogd/repos/staging-i686/PKGBUILD (from rev 288996, ulogd/trunk/PKGBUILD) =================================================================== --- staging-i686/PKGBUILD (rev 0) +++ staging-i686/PKGBUILD 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,82 @@ +# $Id$ +# Maintainer: Sébastien "Seblu" Luttringer <se...@archlinux.org> +# Contributor: Sergej Pupykin <pupykin.s+a...@gmail.com> +# Contributor: Dale Blount <d...@archlinux.org> + +pkgname=ulogd +pkgver=2.0.5 +pkgrel=6 +pkgdesc='Userspace Packet Logging for netfilter' +arch=('i686' 'x86_64') +url='https://www.netfilter.org/projects/ulogd/' +license=('GPL2') +depends=('libmnl' + 'libnetfilter_acct' + 'libnetfilter_conntrack' + 'libnetfilter_log' + 'libnfnetlink') +backup=('etc/ulogd.conf') +makedepends=('libmariadbclient' + 'libpcap' + 'libdbi' + 'postgresql-libs' + 'sqlite' + 'jansson') +optdepends=('libmariadbclient: MySQL databases support' + 'sqlite: SQLite3 databases support' + 'postgresql-libs: PostgreSQL databases support' + 'libdbi: DBI abstraction databases support' + 'libpcap: PCAP output support' + 'jansson: JSON output support') +validpgpkeys=('57FF5E9C9AA67A860B557AF7A4111F89BB5F58CC') # Netfilter Core Team +# 2016-11-03: https sources download is broken with curl +source=("http://www.netfilter.org/projects/ulogd/files/$pkgname-$pkgver.tar.bz2"{,.sig} + "$pkgname.logrotate" + "$pkgname.conf" + "$pkgname.service" + '01-fix-FS#48318.patch') +md5sums=('f0f8fe1371fa28b5e06cb16aaa0111dd' + 'SKIP' + '50c392d3668ee9c69281f05f55430d0f' + '2c8cbedb2fb455cba220ca35186ad846' + '23a13ee4c118cb40b086bdb23d25eac2' + '9b6b3791a1da9433e1779aa5155fdc4a') + +prepare() { + cd $pkgname-$pkgver + # apply patch from the source array (should be a pacman feature) + local filename + for filename in "${source[@]}"; do + if [[ "$filename" =~ \.patch$ ]]; then + msg2 "Applying patch ${filename##*/}" + patch -p1 -N -i "$srcdir/${filename##*/}" + fi + done + : +} + +build() { + cd $pkgname-$pkgver + ./configure \ + --prefix=/usr \ + --sbindir=/usr/bin \ + --sysconfdir=/etc \ + --with-mysql \ + --with-pgsql \ + --with-dbi + make +} + +package() { + cd $pkgname-$pkgver + make DESTDIR="$pkgdir" install + install -dm755 "$pkgdir/usr/share/doc/ulogd" + install -Dm644 ulogd.conf "$pkgdir/usr/share/doc/ulogd/ulogd.conf" + install -m644 doc/*.{table,sql} "$pkgdir/usr/share/doc/ulogd" + cd "$srcdir" + install -Dm644 $pkgname.service "$pkgdir/usr/lib/systemd/system/$pkgname.service" + install -Dm644 $pkgname.logrotate "$pkgdir/etc/logrotate.d/$pkgname" + install -Dm644 $pkgname.conf "$pkgdir/etc/$pkgname.conf" +} + +# vim:set ts=2 sw=2 et: Copied: ulogd/repos/staging-i686/ulogd.conf (from rev 288996, ulogd/trunk/ulogd.conf) =================================================================== --- staging-i686/ulogd.conf (rev 0) +++ staging-i686/ulogd.conf 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,20 @@ +[global] +logfile="/var/log/ulogd.log" +loglevel=5 +rmem=131071 +bufsize=150000 + +plugin="/usr/lib/ulogd/ulogd_inppkt_NFLOG.so" +plugin="/usr/lib/ulogd/ulogd_raw2packet_BASE.so" +plugin="/usr/lib/ulogd/ulogd_filter_IP2STR.so" +plugin="/usr/lib/ulogd/ulogd_filter_PRINTPKT.so" +plugin="/usr/lib/ulogd/ulogd_output_LOGEMU.so" +plugin="/usr/lib/ulogd/ulogd_filter_IFINDEX.so" + +stack=log1:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,emu1:LOGEMU + +[log1] +group=1 + +[emu1] +file=/var/log/ulogd.syslogemu Copied: ulogd/repos/staging-i686/ulogd.logrotate (from rev 288996, ulogd/trunk/ulogd.logrotate) =================================================================== --- staging-i686/ulogd.logrotate (rev 0) +++ staging-i686/ulogd.logrotate 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,10 @@ +/var/log/ulogd.log /var/log/ulogd.syslogemu { + missingok + notifempty + sharedscripts + create 0640 root root + + postrotate + systemctl reload ulogd.service || true + endscript +} Copied: ulogd/repos/staging-i686/ulogd.service (from rev 288996, ulogd/trunk/ulogd.service) =================================================================== --- staging-i686/ulogd.service (rev 0) +++ staging-i686/ulogd.service 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,11 @@ +[Unit] +Description=Netfilter Ulogd daemon +Before=network-pre.target +Wants=network-pre.target + +[Service] +ExecStart=/usr/bin/ulogd +ExecReload=/usr/bin/kill --signal HUP ${MAINPID} + +[Install] +WantedBy=multi-user.target Copied: ulogd/repos/staging-x86_64/01-fix-FS#48318.patch (from rev 288996, ulogd/trunk/01-fix-FS#48318.patch) =================================================================== --- staging-x86_64/01-fix-FS#48318.patch (rev 0) +++ staging-x86_64/01-fix-FS#48318.patch 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,312 @@ +From 1f70d2ba45e2b067777d5386b8d3f2e09be9118b Mon Sep 17 00:00:00 2001 +From: Hironobu Ishii <ishii.hiron...@jp.fujitsu.com> +Date: Tue, 2 Feb 2016 23:01:41 +0900 +Subject: ulogd: restructures signal handling by self-pipe trick + +ulogd had a critical bug that is calling Async-Signal-Unsafe functions +in signal hander context. + - Most of libc functions like fopen(), malloc() are Async-Signal-Unsafe. + So you should not call these functions in signal handler context. + - Calling pluginstances in signal handler context is danger. + For implementer of pluginstances, it is very hard to recognize their + functions are called in signal handler context. + +To solve the issue, I restructured signal handling by self-pipe trick. +For more detail on self-pipe trick, please see the following. +https://lwn.net/Articles/177897/ + +This patch will solve various symptoms like following. + - Deadlock + - Segmentation fault caused by libc management data corruption, + - Other unpredictable behavior. + +Deadlock example +================ +This bug was already filed at: +https://bugzilla.netfilter.org/show_bug.cgi?id=1030 + +I also hit this bug. The backtrace of this issue is following. +In this case, main thread was calling ctime(), +and signal handler called localtime_r(). +That caused the dead lock while getting tzset_lock in __tz_convert(). +Because vsyslog() is Async-Signal-Unsafe function, we cannot call +this function in signal handler context. + + (gdb) bt + #0 __lll_lock_wait_private () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95 + #1 0x00007f3c3fc7e4ac in _L_lock_2462 () at tzset.c:621 + #2 0x00007f3c3fc7e2e7 in __tz_convert (timer=0x7f3c3ff8bf00 <tzset_lock>, + timer@entry=0x7fffcfa923b8, use_localtime=use_localtime@entry=1, + tp=tp@entry=0x7fffcfa92400) at tzset.c:624 + #3 0x00007f3c3fc7c28d in __localtime_r (t=t@entry=0x7fffcfa923b8, + tp=tp@entry=0x7fffcfa92400) at localtime.c:32 + #4 0x00007f3c3fcbf1ba in __GI___vsyslog_chk (pri=<optimized out>, flag=1, + fmt=0x406fa8 "signal received, calling pluginstances\n", ap=0x7fffcfa924a0) + at ../misc/syslog.c:199 + #5 0x00000000004037b5 in __ulogd_log () + #6 0x00000000004047be in signal_handler () + #7 <signal handler called> + #8 0x00007f3c3fcb62f5 in __GI___xstat (vers=<optimized out>, + name=0x7f3c3fd4b2c3 "/etc/localtime", buf=0x7fffcfa92c10) + at ../sysdeps/unix/sysv/linux/wordsize-64/xstat.c:37 + #9 0x00007f3c3fc7e5f6 in __tzfile_read (file=file@entry=0x7f3c3fd4b2c3 "/etc/localtime", + extra=extra@entry=0, extrap=extrap@entry=0x0) at tzfile.c:170 + #10 0x00007f3c3fc7d954 in tzset_internal (always=<optimized out>, + explicit=explicit@entry=1) at tzset.c:444 + #11 0x00007f3c3fc7e303 in __tz_convert (timer=0x7fffcfa92d50, + use_localtime=use_localtime@entry=1, tp=tp@entry=0x7f3c3ff8ed80 <_tmbuf>) + at tzset.c:629 + #12 0x00007f3c3fc7c2a1 in __GI_localtime (t=<optimized out>) at localtime.c:42 + #13 0x00007f3c3fc7c1f9 in ctime (t=<optimized out>) at ctime.c:27 + #14 0x00007f3c3e180ec2 in ?? () + #15 0x0000000056a100c2 in ?? () + #16 0xf8570f79d4fc4200 in ?? () + #17 0x000000000209bec0 in ?? () + #18 0x00007f3c4059f1f8 in ?? () + #19 0x000000000000003c in ?? () + #20 0x0000000000404952 in ulogd_propagate_results () + #21 0x00007f3c3f9cc203 in ?? () + #22 0x0000000000000000 in ?? () + +Segmentation fault in free() +============================ +>From my experience, I think this was caused by some routine called +malloc()/free() in signal handler context. +By that, malloc() management data became inconsistent. +As a result, free() made a wrong dereference. + +Program terminated with signal SIGSEGV, Segmentation fault. + #0 __GI___libc_free (mem=0x7f430f011000) at malloc.c:2903 + 2903 if (chunk_is_mmapped(p)) /* release mmapped memory. */ + (gdb) bt + #0 __GI___libc_free (mem=0x7f430f011000) at malloc.c:2903 + #1 0x00007f430e68affa in __GI__IO_free_backup_area (fp=fp@entry=0x742500) + at genops.c:210 + #2 0x00007f430e68a795 in _IO_new_file_overflow (f=0x742500, ch=-1) at fileops.c:849 + #3 0x00007f430e689511 in _IO_new_file_xsputn (f=0x742500, data=<optimized out>, n=15) + at fileops.c:1372 + #4 0x00007f430e65aa4d in _IO_vfprintf_internal (s=s@entry=0x742500, + format=<optimized out>, format@entry=0x7f430cbc4008 "%.15s %s %s", + ap=ap@entry=0x7fff456ece38) at vfprintf.c:1635 + #5 0x00007f430e71d615 in ___fprintf_chk (fp=0x742500, flag=flag@entry=1, + format=format@entry=0x7f430cbc4008 "%.15s %s %s") at fprintf_chk.c:36 + #6 0x00007f430cbc3f04 in fprintf (__fmt=0x7f430cbc4008 "%.15s %s %s", + __stream=<optimized out>) at /usr/include/bits/stdio2.h:97 + #7 _output_logemu (upi=0x74e5a0) at ulogd_output_LOGEMU.c:102 + #8 0x0000000000404952 in ulogd_propagate_results () + #9 0x00007f430e40f203 in interp_packet (ldata=0x7fff456ed060, pf_family=2 '\002', + upi=0x74a6b0) at ulogd_inppkt_NFLOG.c:400 + #10 msg_cb (gh=<optimized out>, nfmsg=0x7f430efe2020, nfa=0x7fff456ed060, data=0x74a6b0) + at ulogd_inppkt_NFLOG.c:483 + #11 0x00007f430e20a307 in __nflog_rcv_pkt (nlh=<optimized out>, nfa=<optimized out>, + data=<optimized out>) at libnetfilter_log.c:160 + #12 0x00007f430e0056b7 in __nfnl_handle_msg (len=268, nlh=0x7f430efe2010, h=0x74e8e0) + at libnfnetlink.c:1236 + #13 nfnl_handle_packet (h=0x74e8e0, buf=0x7f430efe2010 "\f\001", len=<optimized out>) + at libnfnetlink.c:1256 + #14 0x00007f430e20a508 in nflog_handle_packet (h=<optimized out>, buf=<optimized out>, + len=<optimized out>) at libnetfilter_log.c:323 + #15 0x00007f430e40eaed in nful_read_cb (fd=<optimized out>, what=<optimized out>, + param=0x74a6b0) at ulogd_inppkt_NFLOG.c:463 + #16 0x0000000000404ee0 in ulogd_select_main () + #17 0x0000000000402b17 in main () + +Signed-off-by: Hironobu Ishii <ishii.hiron...@jp.fujitsu.com> +--- + src/ulogd.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 125 insertions(+), 7 deletions(-) + +diff --git a/src/ulogd.c b/src/ulogd.c +index 958c30a..c8d9376 100644 +--- a/src/ulogd.c ++++ b/src/ulogd.c +@@ -90,6 +90,29 @@ static int info_mode = 0; + static int verbose = 0; + static int created_pidfile = 0; + ++/* ++ * Using self-pipe trick to handle signals safely. ++ * (To avoid calling Async-Signal-Unsafe functions in signal handler.) ++ * ++ * cf. https://lwn.net/Articles/177897/ ++ * ++ * Capacity of pipe(2) buffer is >= 4096. ++ */ ++static int signal_channel[2] = { -1, -1 }; /* initialize with invalid fd */ ++#define SIGNAL_RX_FD (signal_channel[0]) /* main thread select() this fd */ ++#define SIGNAL_TX_FD (signal_channel[1]) /* signal handler writes to this fd */ ++ ++static void signal_handler(int signal); ++static void sigterm_handler_task(int signal); ++static void signal_handler_task(int signal); ++ ++static int signal_channel_callback(int fd, unsigned int what, void *data); ++static struct ulogd_fd signal_channel_ulogfd = { ++ .when = ULOGD_FD_READ, ++ .cb = &signal_channel_callback, ++ .data = &signal_channel_ulogfd, ++}; ++ + /* linked list for all registered plugins */ + static LLIST_HEAD(ulogd_plugins); + /* linked list for all plugins handle */ +@@ -387,6 +410,80 @@ void ulogd_register_plugin(struct ulogd_plugin *me) + } + + /*********************************************************************** ++ * UTILITY FUNCTIONS FOR SIGNAL HANDLING ++ ***********************************************************************/ ++static void call_signal_handler_tasks(int sig) ++{ ++ /* Deliver signals */ ++ switch (sig) { ++ case SIGTERM: ++ case SIGINT: ++ sigterm_handler_task(sig); ++ break; ++ case SIGHUP: ++ case SIGALRM: ++ case SIGUSR1: ++ case SIGUSR2: ++ signal_handler_task(sig); ++ break; ++ default: ++ break; ++ } ++} ++ ++static int signal_channel_callback(int fd, unsigned int what, void *data) ++{ ++ int ret; ++ unsigned char c; ++ ++ while ((ret = read(fd, &c, 1)) > 0) { ++ call_signal_handler_tasks((int)c); ++ } ++ return 0; ++} ++ ++static int create_signal_channel(void) ++{ ++ int ret; ++ long flags; ++ ++ if ((ret = pipe(signal_channel)) < 0) ++ return ret; ++ ++ /* SIGNAL_RX_FD, channel[0] */ ++ if ((flags = fcntl(SIGNAL_RX_FD, F_GETFL)) < 0) ++ goto err_exit; ++ flags |= O_NONBLOCK; ++ if ( fcntl(SIGNAL_RX_FD, F_SETFL, flags) < 0 ) ++ goto err_exit; ++ ++ /* SIGNAL_TX_FD, channel[1] */ ++ if ((flags = fcntl(SIGNAL_TX_FD, F_GETFL)) < 0) ++ goto err_exit; ++ flags |= O_NONBLOCK; ++ if ( fcntl(SIGNAL_TX_FD, F_SETFL, flags) < 0 ) ++ goto err_exit; ++ ++ /* register SIGNAL_RX_FD to ulogd */ ++ signal_channel_ulogfd.fd = SIGNAL_RX_FD; ++ ulogd_register_fd(&signal_channel_ulogfd); ++ ++ return 0; ++ ++err_exit: ++ if (SIGNAL_RX_FD >= 0) { ++ (void)close(SIGNAL_RX_FD); ++ SIGNAL_RX_FD = -1; ++ } ++ if (SIGNAL_TX_FD >= 0) { ++ (void)close(SIGNAL_TX_FD); ++ SIGNAL_TX_FD = -1; ++ } ++ return -1; ++} ++ ++ ++/*********************************************************************** + * MAIN PROGRAM + ***********************************************************************/ + +@@ -925,7 +1022,6 @@ static void ulogd_main_loop(void) + struct timeval *next = NULL; + + while (1) { +- /* XXX: signal blocking? */ + if (next != NULL && !timerisset(next)) + next = ulogd_do_timer_run(&next_alarm); + else +@@ -1225,7 +1321,19 @@ static void stop_stack() + } + + +-static void sigterm_handler(int signal) ++/* This is a real SIGTERM, SIGINT, SIGHUP, SIGALRM, SIGUSR1, SIGUSR2 handler */ ++static void signal_handler(int signal) ++{ ++ unsigned char c = (unsigned char)signal; ++ ++ (void)write(SIGNAL_TX_FD, &c, 1); ++} ++ ++/* This is NOT a real signal handler. ++ * It is called in ulogd_main_loop() to avoid ++ * calling Async-Signal-UnSafe functions in signal handler. ++ */ ++static void sigterm_handler_task(int signal) + { + + ulogd_log(ULOGD_NOTICE, "Terminal signal received, exiting\n"); +@@ -1255,7 +1363,12 @@ static void sigterm_handler(int signal) + exit(0); + } + +-static void signal_handler(int signal) ++ ++/* This is NOT a real signal handler. ++ * It is called in ulogd_main_loop() to avoid ++ * calling Async-Signal-UnSafe functions in signal handler. ++ */ ++static void signal_handler_task(int signal) + { + ulogd_log(ULOGD_NOTICE, "signal received, calling pluginstances\n"); + +@@ -1269,7 +1382,7 @@ static void signal_handler(int signal) + fprintf(stderr, + "ERROR: can't open logfile %s: %s\n", + ulogd_logfile, strerror(errno)); +- sigterm_handler(signal); ++ sigterm_handler_task(signal); + } + + } +@@ -1464,8 +1577,13 @@ int main(int argc, char* argv[]) + } + } + +- signal(SIGTERM, &sigterm_handler); +- signal(SIGINT, &sigterm_handler); ++ if (create_signal_channel() < 0) { ++ ulogd_log(ULOGD_FATAL, "can't create signal channel\n"); ++ warn_and_exit(daemonize); ++ } ++ ++ signal(SIGTERM, &signal_handler); ++ signal(SIGINT, &signal_handler); + signal(SIGHUP, &signal_handler); + signal(SIGALRM, &signal_handler); + signal(SIGUSR1, &signal_handler); +@@ -1477,6 +1595,6 @@ int main(int argc, char* argv[]) + ulogd_main_loop(); + + /* hackish, but result is the same */ +- sigterm_handler(SIGTERM); ++ sigterm_handler_task(SIGTERM); + return(0); + } +-- +cgit v0.11.2 + Copied: ulogd/repos/staging-x86_64/PKGBUILD (from rev 288996, ulogd/trunk/PKGBUILD) =================================================================== --- staging-x86_64/PKGBUILD (rev 0) +++ staging-x86_64/PKGBUILD 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,82 @@ +# $Id$ +# Maintainer: Sébastien "Seblu" Luttringer <se...@archlinux.org> +# Contributor: Sergej Pupykin <pupykin.s+a...@gmail.com> +# Contributor: Dale Blount <d...@archlinux.org> + +pkgname=ulogd +pkgver=2.0.5 +pkgrel=6 +pkgdesc='Userspace Packet Logging for netfilter' +arch=('i686' 'x86_64') +url='https://www.netfilter.org/projects/ulogd/' +license=('GPL2') +depends=('libmnl' + 'libnetfilter_acct' + 'libnetfilter_conntrack' + 'libnetfilter_log' + 'libnfnetlink') +backup=('etc/ulogd.conf') +makedepends=('libmariadbclient' + 'libpcap' + 'libdbi' + 'postgresql-libs' + 'sqlite' + 'jansson') +optdepends=('libmariadbclient: MySQL databases support' + 'sqlite: SQLite3 databases support' + 'postgresql-libs: PostgreSQL databases support' + 'libdbi: DBI abstraction databases support' + 'libpcap: PCAP output support' + 'jansson: JSON output support') +validpgpkeys=('57FF5E9C9AA67A860B557AF7A4111F89BB5F58CC') # Netfilter Core Team +# 2016-11-03: https sources download is broken with curl +source=("http://www.netfilter.org/projects/ulogd/files/$pkgname-$pkgver.tar.bz2"{,.sig} + "$pkgname.logrotate" + "$pkgname.conf" + "$pkgname.service" + '01-fix-FS#48318.patch') +md5sums=('f0f8fe1371fa28b5e06cb16aaa0111dd' + 'SKIP' + '50c392d3668ee9c69281f05f55430d0f' + '2c8cbedb2fb455cba220ca35186ad846' + '23a13ee4c118cb40b086bdb23d25eac2' + '9b6b3791a1da9433e1779aa5155fdc4a') + +prepare() { + cd $pkgname-$pkgver + # apply patch from the source array (should be a pacman feature) + local filename + for filename in "${source[@]}"; do + if [[ "$filename" =~ \.patch$ ]]; then + msg2 "Applying patch ${filename##*/}" + patch -p1 -N -i "$srcdir/${filename##*/}" + fi + done + : +} + +build() { + cd $pkgname-$pkgver + ./configure \ + --prefix=/usr \ + --sbindir=/usr/bin \ + --sysconfdir=/etc \ + --with-mysql \ + --with-pgsql \ + --with-dbi + make +} + +package() { + cd $pkgname-$pkgver + make DESTDIR="$pkgdir" install + install -dm755 "$pkgdir/usr/share/doc/ulogd" + install -Dm644 ulogd.conf "$pkgdir/usr/share/doc/ulogd/ulogd.conf" + install -m644 doc/*.{table,sql} "$pkgdir/usr/share/doc/ulogd" + cd "$srcdir" + install -Dm644 $pkgname.service "$pkgdir/usr/lib/systemd/system/$pkgname.service" + install -Dm644 $pkgname.logrotate "$pkgdir/etc/logrotate.d/$pkgname" + install -Dm644 $pkgname.conf "$pkgdir/etc/$pkgname.conf" +} + +# vim:set ts=2 sw=2 et: Copied: ulogd/repos/staging-x86_64/ulogd.conf (from rev 288996, ulogd/trunk/ulogd.conf) =================================================================== --- staging-x86_64/ulogd.conf (rev 0) +++ staging-x86_64/ulogd.conf 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,20 @@ +[global] +logfile="/var/log/ulogd.log" +loglevel=5 +rmem=131071 +bufsize=150000 + +plugin="/usr/lib/ulogd/ulogd_inppkt_NFLOG.so" +plugin="/usr/lib/ulogd/ulogd_raw2packet_BASE.so" +plugin="/usr/lib/ulogd/ulogd_filter_IP2STR.so" +plugin="/usr/lib/ulogd/ulogd_filter_PRINTPKT.so" +plugin="/usr/lib/ulogd/ulogd_output_LOGEMU.so" +plugin="/usr/lib/ulogd/ulogd_filter_IFINDEX.so" + +stack=log1:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,emu1:LOGEMU + +[log1] +group=1 + +[emu1] +file=/var/log/ulogd.syslogemu Copied: ulogd/repos/staging-x86_64/ulogd.logrotate (from rev 288996, ulogd/trunk/ulogd.logrotate) =================================================================== --- staging-x86_64/ulogd.logrotate (rev 0) +++ staging-x86_64/ulogd.logrotate 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,10 @@ +/var/log/ulogd.log /var/log/ulogd.syslogemu { + missingok + notifempty + sharedscripts + create 0640 root root + + postrotate + systemctl reload ulogd.service || true + endscript +} Copied: ulogd/repos/staging-x86_64/ulogd.service (from rev 288996, ulogd/trunk/ulogd.service) =================================================================== --- staging-x86_64/ulogd.service (rev 0) +++ staging-x86_64/ulogd.service 2017-02-14 23:23:47 UTC (rev 288997) @@ -0,0 +1,11 @@ +[Unit] +Description=Netfilter Ulogd daemon +Before=network-pre.target +Wants=network-pre.target + +[Service] +ExecStart=/usr/bin/ulogd +ExecReload=/usr/bin/kill --signal HUP ${MAINPID} + +[Install] +WantedBy=multi-user.target