Test that syslogd sending over TCP does not leak a file descriptor
authorbluhm <bluhm@openbsd.org>
Thu, 1 Jan 2015 19:58:48 +0000 (19:58 +0000)
committerbluhm <bluhm@openbsd.org>
Thu, 1 Jan 2015 19:58:48 +0000 (19:58 +0000)
when it receives a SIGHUP.

regress/usr.sbin/syslogd/LICENSE
regress/usr.sbin/syslogd/Proc.pm
regress/usr.sbin/syslogd/Syslogd.pm
regress/usr.sbin/syslogd/args-sighup-tcp.pl [new file with mode: 0644]
regress/usr.sbin/syslogd/args-sighup.pl
regress/usr.sbin/syslogd/args-socket-tcp.pl [new file with mode: 0644]
regress/usr.sbin/syslogd/funcs.pl

index a6e1dd3..407681a 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org>
+# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org>
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
index 46d7001..37280ee 100644 (file)
@@ -1,6 +1,6 @@
-#      $OpenBSD: Proc.pm,v 1.3 2014/09/13 23:38:24 bluhm Exp $
+#      $OpenBSD: Proc.pm,v 1.4 2015/01/01 19:58:48 bluhm Exp $
 
-# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org>
+# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org>
 # Copyright (c) 2014 Florian Riehm <mail@friehm.de>
 #
 # Permission to use, copy, modify, and distribute this software for any
@@ -112,9 +112,11 @@ sub run {
                system(@cmd)
                    and die ref($self), " system '@cmd' failed: $?";
        }
-       $self->child();
-       print STDERR $self->{up}, "\n";
-       $self->{func}->($self);
+       do {
+               $self->child();
+               print STDERR $self->{up}, "\n";
+               $self->{func}->($self);
+       } while ($self->{redo});
        print STDERR "Shutdown", "\n";
 
        IO::Handle::flush(\*STDOUT);
index b70a8ea..bc23308 100644 (file)
@@ -1,6 +1,6 @@
-#      $OpenBSD: Syslogd.pm,v 1.7 2014/12/28 14:08:01 bluhm Exp $
+#      $OpenBSD: Syslogd.pm,v 1.8 2015/01/01 19:58:48 bluhm Exp $
 
-# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org>
+# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org>
 # Copyright (c) 2014 Florian Riehm <mail@friehm.de>
 #
 # Permission to use, copy, modify, and distribute this software for any
@@ -126,21 +126,27 @@ sub up {
        my $self = Proc::up(shift, @_);
 
        if ($self->{fstat}) {
-               open(my $fh, '>', $self->{fstatfile}) or die ref($self),
-                   " open $self->{fstatfile} for writing failed: $!";
-               my @cmd = ("fstat");
-               open(my $fs, '-|', @cmd)
-                   or die ref($self), " open pipe from '@cmd' failed: $!";
-               print $fh grep { /^\w+ *syslogd *\d+/ } <$fs>;
-               close($fs) or die ref($self), $! ?
-                   " close pipe from '@cmd' failed: $!" :
-                   " command '@cmd' failed: $?";
-               close($fh)
-                   or die ref($self), " close $self->{fstatfile} failed: $!";
+               $self->fstat;
        }
        return $self;
 }
 
+sub fstat {
+       my $self = shift;
+
+       open(my $fh, '>', $self->{fstatfile}) or die ref($self),
+           " open $self->{fstatfile} for writing failed: $!";
+       my @cmd = ("fstat");
+       open(my $fs, '-|', @cmd)
+           or die ref($self), " open pipe from '@cmd' failed: $!";
+       print $fh grep { /^\w+ *syslogd *\d+/ } <$fs>;
+       close($fs) or die ref($self), $! ?
+           " close pipe from '@cmd' failed: $!" :
+           " command '@cmd' failed: $?";
+       close($fh)
+           or die ref($self), " close $self->{fstatfile} failed: $!";
+}
+
 sub _make_abspath {
        my $file = ref($_[0]) ? ${$_[0]} : $_[0];
        if (substr($file, 0, 1) ne "/") {
diff --git a/regress/usr.sbin/syslogd/args-sighup-tcp.pl b/regress/usr.sbin/syslogd/args-sighup-tcp.pl
new file mode 100644 (file)
index 0000000..0a31dbd
--- /dev/null
@@ -0,0 +1,71 @@
+# The client writes a message to Sys::Syslog native method.
+# The syslogd writes it into a file and through a pipe.
+# The syslogd passes it via TCP to the loghost.
+# The server receives the message on its TCP socket.
+# Find the message in client, file, pipe, syslogd, server log.
+# Check that a SIGHUP reconnects the TCP stream and closes the socket.
+
+use strict;
+use warnings;
+
+our %args = (
+    client => {
+       func => sub {
+           my $self = shift;
+           write_between2logs($self, sub {
+               ${$self->{server}}->loggrep("Signal", 8)
+                   or die ref($self), " no 'Signal' between logs";
+           });
+       },
+       loggrep => { get_between2loggrep() },
+    },
+    syslogd => {
+       ktrace => 1,
+       fstat => 1,
+       kdump => {
+           qr/syslogd  PSIG  SIGHUP caught handler/ => 1,
+           qr/syslogd  RET   execve 0/ => 1,
+       },
+       loghost => '@tcp://127.0.0.1:$connectport',
+       loggrep => {
+           qr/config file changed: dying/ => 0,
+           qr/config file modified: restarting/ => 0,
+           qr/syslogd: restarted/ => 1,
+           get_between2loggrep(),
+       },
+    },
+    server => {
+       listen => { domain => AF_INET, addr => "127.0.0.1", proto => "tcp" },
+       redo => 0,
+       func => sub {
+           my $self = shift;
+           read_between2logs($self, sub {
+               if ($self->{redo}) {
+                       $self->{redo}--;
+                       return;
+               }
+               ${$self->{syslogd}}->rotate();
+               ${$self->{syslogd}}->kill_syslogd('HUP');
+               ${$self->{syslogd}}->loggrep("syslogd: restarted", 5)
+                   or die ref($self), " no 'syslogd: restarted' between logs";
+               print STDERR "Signal\n";
+               # regeneate fstat file
+               ${$self->{syslogd}}->fstat();
+               $self->{redo}++;
+           });
+       },
+       loggrep => {
+           get_between2loggrep(),
+           qr/Signal/ => 1,
+           qr/Accepted/ => 2,
+       },
+    },
+    fstat => {
+       loggrep => {
+           # sighup must not leak a TCP socket
+           qr/internet stream tcp/ => 1,
+       },
+    },
+);
+
+1;
index 63ffe2c..b375ebb 100644 (file)
@@ -43,7 +43,11 @@ our %args = (
                print STDERR "Signal\n";
            });
        },
-       loggrep => { get_between2loggrep() },
+       loggrep => {
+           get_between2loggrep(),
+           qr/Signal/ => 1,
+           qr/Accepted/ => 1,
+       },
     },
     check => sub {
        my $self = shift;
diff --git a/regress/usr.sbin/syslogd/args-socket-tcp.pl b/regress/usr.sbin/syslogd/args-socket-tcp.pl
new file mode 100644 (file)
index 0000000..cbd8bee
--- /dev/null
@@ -0,0 +1,29 @@
+# Test with default values, that is:
+# The client writes a message to a localhost IPv4 TCP socket.
+# The syslogd writes it into a file and through a pipe.
+# The syslogd passes it via TCP to the loghost.
+# The server receives the message on its TCP socket.
+# Find the message in client, file, pipe, syslogd, server log.
+# Check that the syslogd has one TCP socket in fstat output.
+
+use strict;
+use warnings;
+use Socket;
+
+our %args = (
+    syslogd => {
+       fstat => 1,
+       loghost => '@tcp://127.0.0.1:$connectport',
+       options => ["-n"],
+    },
+    server => {
+       listen => { domain => AF_INET, addr => "127.0.0.1", proto => "tcp" },
+    },
+    fstat => {
+       loggrep => {
+           qr/ internet stream tcp / => 1,
+       },
+    },
+);
+
+1;
index d71d73b..382ab1f 100644 (file)
@@ -1,6 +1,6 @@
-#      $OpenBSD: funcs.pl,v 1.8 2014/12/28 14:08:01 bluhm Exp $
+#      $OpenBSD: funcs.pl,v 1.9 2015/01/01 19:58:48 bluhm Exp $
 
-# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org>
+# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org>
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -115,10 +115,14 @@ sub read_between2logs {
        my $self = shift;
        my $func = shift;
 
-       read_message($self, $firstlog, @_);
+       unless ($self->{redo}) {
+               read_message($self, $firstlog, @_);
+       }
        $func->($self, @_);
-       read_message($self, $testlog, @_);
-       read_message($self, $downlog, @_);
+       unless ($self->{redo}) {
+               read_message($self, $testlog, @_);
+               read_message($self, $downlog, @_);
+       }
 }
 
 sub read_message {
@@ -128,8 +132,9 @@ sub read_message {
        local $_;
        for (;;) {
                # reading udp packets works only with sysread()
-               defined(sysread(STDIN, $_, 8194))
+               defined(my $n = sysread(STDIN, $_, 8194))
                    or die ref($self), " read log line failed: $!";
+               last if $n == 0;
                chomp;
                print STDERR ">>> $_\n";
                last if /$regex/;