Rework how fstat and ktrace pattern are specified in the test
authorbluhm <bluhm@openbsd.org>
Mon, 15 Jun 2015 21:44:57 +0000 (21:44 +0000)
committerbluhm <bluhm@openbsd.org>
Mon, 15 Jun 2015 21:44:57 +0000 (21:44 +0000)
arguments.  Add tests to check wether syslogd privsep works.  This
is done for debug and foreground and daemon mode.  Fstat is checked
for chroot and sockets.  Ktrace dump is grepped for setting uid and
gid.

27 files changed:
regress/usr.sbin/syslogd/Makefile
regress/usr.sbin/syslogd/Syslogd.pm
regress/usr.sbin/syslogd/args-length-tcp.pl
regress/usr.sbin/syslogd/args-length-tls.pl
regress/usr.sbin/syslogd/args-length-udp.pl
regress/usr.sbin/syslogd/args-length-unix.pl
regress/usr.sbin/syslogd/args-length-vis.pl
regress/usr.sbin/syslogd/args-libevent-kqueue.pl
regress/usr.sbin/syslogd/args-libevent-poll.pl
regress/usr.sbin/syslogd/args-libevent-select.pl
regress/usr.sbin/syslogd/args-only4.pl
regress/usr.sbin/syslogd/args-only6.pl
regress/usr.sbin/syslogd/args-privsep-daemon.pl [new file with mode: 0644]
regress/usr.sbin/syslogd/args-privsep-foreground.pl [new file with mode: 0644]
regress/usr.sbin/syslogd/args-privsep.pl [new file with mode: 0644]
regress/usr.sbin/syslogd/args-sendsyslog.pl
regress/usr.sbin/syslogd/args-sighup-config.pl
regress/usr.sbin/syslogd/args-sighup-privsep.pl
regress/usr.sbin/syslogd/args-sighup-tcp.pl
regress/usr.sbin/syslogd/args-sighup-tls.pl
regress/usr.sbin/syslogd/args-sighup.pl
regress/usr.sbin/syslogd/args-sigpipe.pl
regress/usr.sbin/syslogd/args-sigterm.pl
regress/usr.sbin/syslogd/args-socket-tcp.pl
regress/usr.sbin/syslogd/args-socket-tls.pl
regress/usr.sbin/syslogd/args-socket.pl
regress/usr.sbin/syslogd/funcs.pl

index 83a6e5d..d0f8d56 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.8 2015/01/28 19:23:22 bluhm Exp $
+#      $OpenBSD: Makefile,v 1.9 2015/06/15 21:44:57 bluhm Exp $
 
 # The following ports must be installed for the regression tests:
 # p5-IO-Socket-INET6   object interface for AF_INET and AF_INET6 domain sockets
@@ -41,6 +41,7 @@ CLEANFILES +=         *.pem *.req *.crt *.key *.srl empty toobig
 .BEGIN:
        @echo
        [ -z "${SUDO}" ] || ${SUDO} true
+       ${SUDO} /etc/rc.d/syslogd stop
 .END:
        @echo
        ${SUDO} /etc/rc.d/syslogd restart
index 94e5f5a..8aa6f6f 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Syslogd.pm,v 1.11 2015/02/13 21:40:50 bluhm Exp $
+#      $OpenBSD: Syslogd.pm,v 1.12 2015/06/15 21:44:57 bluhm Exp $
 
 # Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org>
 # Copyright (c) 2014 Florian Riehm <mail@friehm.de>
@@ -23,6 +23,7 @@ use parent 'Proc';
 use Carp;
 use Cwd;
 use File::Basename;
+use Time::HiRes qw(time alarm sleep);
 
 sub new {
        my $class = shift;
@@ -32,6 +33,10 @@ sub new {
        $args{logfile} ||= "syslogd.log";
        $args{up} ||= "syslogd: started";
        $args{down} ||= "syslogd: exiting";
+       $args{up} = $args{down} = "execute:"
+           if $args{foreground} || $args{daemon};
+       $args{foreground} && $args{daemon}
+           and croak "$class cannot run in foreground and as daemon";
        $args{func} = sub { Carp::confess "$class func may not be called" };
        $args{conffile} ||= "syslogd.conf";
        $args{outfile} ||= "file.log";
@@ -113,9 +118,11 @@ sub child {
        @ktrace = "ktrace" if $self->{ktrace} && !@ktrace;
        push @ktrace, "-i", "-f", $self->{ktracefile} if @ktrace;
        my $syslogd = $ENV{SYSLOGD} ? $ENV{SYSLOGD} : "syslogd";
-       my @cmd = (@sudo, @libevent, @ktrace, $syslogd, "-d",
+       my @cmd = (@sudo, @libevent, @ktrace, $syslogd,
            "-f", $self->{conffile});
-       push @cmd, "-V", unless $self->{cacrt};
+       push @cmd, "-d" if !$self->{foreground} && !$self->{daemon};
+       push @cmd, "-F" if $self->{foreground};
+       push @cmd, "-V" unless $self->{cacrt};
        push @cmd, "-C", $self->{cacrt}
            if $self->{cacrt} && $self->{cacrt} ne "default";
        push @cmd, "-s", $self->{ctlsock} if $self->{ctlsock};
@@ -127,9 +134,23 @@ sub child {
 
 sub up {
        my $self = Proc::up(shift, @_);
-
-       if ($self->{fstat}) {
-               $self->fstat;
+       my $timeout = shift || 10;
+
+       my $end = time() + $timeout;
+
+       while ($self->{fstat}) {
+               $self->fstat();
+               last unless $self->{foreground} || $self->{daemon};
+
+               # in foreground mode and as daemon we have no debug output
+               # check fstat kqueue entry to detect statup
+               open(my $fh, '<', $self->{fstatfile}) or die ref($self),
+                   " open $self->{fstatfile} for reading failed: $!";
+               last if grep { /kqueue/ } <$fh>;
+               time() < $end
+                   or croak ref($self), " no 'kqueue' in $self->{fstatfile} ".
+                   "after $timeout seconds";
+               sleep .1;
        }
        return $self;
 }
index da83deb..5cd5374 100644 (file)
@@ -23,7 +23,7 @@ our %args = (
        options => ["-u"],
        loggrep => {
            get_charlog() => 5,
-       }
+       },
     },
     server => {
        listen => { domain => AF_UNSPEC, proto => "tcp", addr => "localhost" },
index 7da418c..baaae5f 100644 (file)
@@ -23,7 +23,7 @@ our %args = (
        options => ["-u"],
        loggrep => {
            get_charlog() => 5,
-       }
+       },
     },
     server => {
        listen => { domain => AF_UNSPEC, proto => "tls", addr => "localhost" },
index b757146..9a5d602 100644 (file)
@@ -23,7 +23,7 @@ our %args = (
        options => ["-u"],
        loggrep => {
            get_charlog() => 5,
-       }
+       },
     },
     server => {
        # >>> <13>Jan 31 00:10:11 0123456789ABC...lmn
index e84e843..74431ec 100644 (file)
@@ -21,7 +21,7 @@ our %args = (
     syslogd => {
        loggrep => {
            get_charlog() => 5,
-       }
+       },
     },
     file => {
        # Feb  2 00:43:36 hostname 0123456789ABC...567
index e9104d6..c3f03c2 100644 (file)
@@ -22,7 +22,7 @@ our %args = (
        options => ["-u"],
        loggrep => {
            get_charlog() => 11,
-       }
+       },
     },
     file => {
        # Jan 31 00:12:39 localhost 0123456789ABC...567
index 570c5ee..15d925e 100644 (file)
@@ -15,8 +15,7 @@ $ENV{EVENT_NOSELECT} = 1;
 our %args = (
     syslogd => {
        loggrep => qr/libevent using: kqueue/,
-       ktrace => 1,
-       kdump => qr/CALL  kqueue/,
+       ktrace => qr/CALL  kqueue/,
     },
 );
 
index 1dd688a..b06fbc6 100644 (file)
@@ -15,8 +15,7 @@ $ENV{EVENT_NOSELECT} = 1;
 our %args = (
     syslogd => {
        loggrep => qr/libevent using: poll/,
-       ktrace => 1,
-       kdump => qr/CALL  poll/,
+       ktrace => qr/CALL  poll/,
     },
 );
 
index 9c9bb36..2643369 100644 (file)
@@ -15,8 +15,7 @@ $ENV{EVENT_NOSELECT} = 0;
 our %args = (
     syslogd => {
        loggrep => qr/libevent using: select/,
-       ktrace => 1,
-       kdump => qr/CALL  select/,
+       ktrace => qr/CALL  select/,
     },
 );
 
index db4d9df..e6993f5 100644 (file)
@@ -14,7 +14,9 @@ our %args = (
        connect => { domain => AF_INET, addr => "127.0.0.1", port => 514 },
     },
     syslogd => {
-       fstat => 1,
+       fstat => {
+           qr/ internet6 / => 0,
+       },
        loghost => '@127.0.0.1:$connectport',
        options => ["-4nu"],
     },
@@ -24,11 +26,6 @@ our %args = (
     file => {
        loggrep => qr/ 127.0.0.1 /. get_testlog(),
     },
-    fstat => {
-       loggrep => {
-           qr/ internet6 / => 0,
-       },
-    },
 );
 
 1;
index bda7243..1107286 100644 (file)
@@ -14,7 +14,9 @@ our %args = (
        connect => { domain => AF_INET6, addr => "::1", port => 514 },
     },
     syslogd => {
-       fstat => 1,
+       fstat => {
+           qr/ internet / => 0,
+       },
        loghost => '@[::1]:$connectport',
        options => ["-6nu"],
     },
@@ -24,11 +26,6 @@ our %args = (
     file => {
        loggrep => qr/ ::1 /. get_testlog(),
     },
-    fstat => {
-       loggrep => {
-           qr/ internet / => 0,
-       },
-    },
 );
 
 1;
diff --git a/regress/usr.sbin/syslogd/args-privsep-daemon.pl b/regress/usr.sbin/syslogd/args-privsep-daemon.pl
new file mode 100644 (file)
index 0000000..6c8f814
--- /dev/null
@@ -0,0 +1,45 @@
+# Start syslogd in daemon mode.
+# 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 UDP to the loghost.
+# The server receives the message on its UDP socket.
+# Find the message in client, file, syslogd, server log.
+# Check fstat for the parent and child process.
+# Check ktrace for setting the correct uid and gid.
+# Check that stdio is dupped to /dev/null.
+
+use strict;
+use warnings;
+
+our %args = (
+    syslogd => {
+       daemon => 1,
+       loggrep => {
+           qr/ -F / => 0,
+           qr/ -d / => 0,
+       },
+       fstat => {
+           qr/^root .* wd / => 1,
+           qr/^root .* root / => 0,
+           qr/^root .* [012] .* null$/ => 3,
+           qr/^root .* kqueue / => 0,
+           qr/^root .* internet/ => 0,
+           qr/^_syslogd .* wd / => 1,
+           qr/^_syslogd .* root / => 1,
+           qr/^_syslogd .* [012] .* null$/ => 3,
+           qr/^_syslogd .* kqueue / => 1,
+           qr/^_syslogd .* internet/ => 2,
+       },
+       ktrace => {
+           qr/CALL  setresuid(.*"_syslogd".*){3}/ => 2,
+           qr/CALL  setresgid(.*"_syslogd".*){3}/ => 2,
+           qr/CALL  setsid/ => 1,
+           qr/RET   setsid.* errno / => 0,
+       },
+    },
+    pipe => {
+       nocheck => 1,
+    },
+);
+
+1;
diff --git a/regress/usr.sbin/syslogd/args-privsep-foreground.pl b/regress/usr.sbin/syslogd/args-privsep-foreground.pl
new file mode 100644 (file)
index 0000000..33053a8
--- /dev/null
@@ -0,0 +1,44 @@
+# Start syslogd in foreground mode.
+# 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 UDP to the loghost.
+# The server receives the message on its UDP socket.
+# Find the message in client, file, syslogd, server log.
+# Check fstat for the parent and child process.
+# Check ktrace for setting the correct uid and gid.
+# Check that stdio is dupped to /dev/null.
+
+use strict;
+use warnings;
+
+our %args = (
+    syslogd => {
+       foreground => 1,
+       loggrep => {
+           qr/ -F / => 1,
+           qr/ -d / => 0,
+       },
+       fstat => {
+           qr/^root .* wd / => 1,
+           qr/^root .* root / => 0,
+           qr/^root .* [012] .* null$/ => 3,
+           qr/^root .* kqueue / => 0,
+           qr/^root .* internet/ => 0,
+           qr/^_syslogd .* wd / => 1,
+           qr/^_syslogd .* root / => 1,
+           qr/^_syslogd .* [012] .* null$/ => 3,
+           qr/^_syslogd .* kqueue / => 1,
+           qr/^_syslogd .* internet/ => 2,
+       },
+       ktrace => {
+           qr/CALL  setresuid(.*"_syslogd".*){3}/ => 2,
+           qr/CALL  setresgid(.*"_syslogd".*){3}/ => 2,
+           qr/CALL  setsid/ => 0,
+       },
+    },
+    pipe => {
+       nocheck => 1,
+    },
+);
+
+1;
diff --git a/regress/usr.sbin/syslogd/args-privsep.pl b/regress/usr.sbin/syslogd/args-privsep.pl
new file mode 100644 (file)
index 0000000..d88e274
--- /dev/null
@@ -0,0 +1,36 @@
+# 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 UDP to the loghost.
+# The server receives the message on its UDP socket.
+# Find the message in client, file, pipe, syslogd, server log.
+# Check fstat for the parent and child process.
+# Check ktrace for setting the correct uid and gid.
+
+use strict;
+use warnings;
+
+our %args = (
+    syslogd => {
+       loggrep => {
+           qr/ -F / => 0,
+           qr/ -d / => 1,
+       },
+       fstat => {
+           qr/^root .* wd / => 1,
+           qr/^root .* root / => 0,
+           qr/^root .* kqueue / => 0,
+           qr/^root .* internet/ => 0,
+           qr/^_syslogd .* wd / => 1,
+           qr/^_syslogd .* root / => 1,
+           qr/^_syslogd .* kqueue / => 1,
+           qr/^_syslogd .* internet/ => 2,
+       },
+       ktrace => {
+           qr/CALL  setresuid(.*"_syslogd".*){3}/ => 2,
+           qr/CALL  setresgid(.*"_syslogd".*){3}/ => 2,
+           qr/CALL  setsid/ => 0,
+       },
+    },
+);
+
+1;
index b29b25a..18f7163 100644 (file)
@@ -11,8 +11,7 @@ use warnings;
 
 our %args = (
     client => {
-       ktrace => 1,
-       kdump => {
+       ktrace => {
            qr/CALL  sendsyslog/ => 2,
            qr/GIO   fd -1 wrote \d+ bytes/ => 2,
            qr/RET   sendsyslog 0/ => 2,
index a6c64e3..6f03753 100644 (file)
@@ -18,8 +18,7 @@ our %args = (
        loggrep => { get_between2loggrep() },
     },
     syslogd => {
-       ktrace => 1,
-       kdump => {
+       ktrace => {
            qr/syslogd  PSIG  SIGHUP caught handler/ => 1,
            qr/syslogd  RET   execve 0/ => 2,
        },
index 8341586..e7f2b75 100644 (file)
@@ -18,8 +18,7 @@ our %args = (
        loggrep => { get_between2loggrep() },
     },
     syslogd => {
-       ktrace => 1,
-       kdump => {
+       ktrace => {
            qr/syslogd  PSIG  SIGHUP caught handler/ => 2,
            qr/syslogd  RET   execve 0/ => 1,
        },
index ba26557..5a6c841 100644 (file)
@@ -19,9 +19,11 @@ our %args = (
        loggrep => { get_between2loggrep() },
     },
     syslogd => {
-       ktrace => 1,
-       fstat => 1,
-       kdump => {
+       fstat => {
+           # sighup must not leak a TCP socket
+           qr/internet stream tcp/ => 1,
+       },
+       ktrace => {
            qr/syslogd  PSIG  SIGHUP caught handler/ => 1,
            qr/syslogd  RET   execve 0/ => 1,
        },
@@ -57,12 +59,6 @@ our %args = (
            qr/Accepted/ => 2,
        },
     },
-    fstat => {
-       loggrep => {
-           # sighup must not leak a TCP socket
-           qr/internet stream tcp/ => 1,
-       },
-    },
 );
 
 1;
index 20b04b1..f97c200 100644 (file)
@@ -19,9 +19,11 @@ our %args = (
        loggrep => { get_between2loggrep() },
     },
     syslogd => {
-       ktrace => 1,
-       fstat => 1,
-       kdump => {
+       fstat => {
+           # sighup must not leak a TCP socket
+           qr/internet stream tcp/ => 1,
+       },
+       ktrace => {
            qr/syslogd  PSIG  SIGHUP caught handler/ => 1,
            qr/syslogd  RET   execve 0/ => 1,
        },
@@ -57,12 +59,6 @@ our %args = (
            qr/Accepted/ => 2,
        },
     },
-    fstat => {
-       loggrep => {
-           # sighup must not leak a TCP socket
-           qr/internet stream tcp/ => 1,
-       },
-    },
 );
 
 1;
index 41b4b0d..c8dc56a 100644 (file)
@@ -18,8 +18,7 @@ our %args = (
        loggrep => { get_between2loggrep() },
     },
     syslogd => {
-       ktrace => 1,
-       kdump => {
+       ktrace => {
            qr/syslogd  PSIG  SIGHUP caught handler/ => 1,
            qr/syslogd  RET   execve 0/ => 1,
        },
index 7bf9259..a74f8ae 100644 (file)
@@ -18,8 +18,7 @@ our %args = (
        loggrep => { get_between2loggrep() },
     },
     syslogd => {
-       ktrace => 1,
-       kdump => {
+       ktrace => {
            qr/syslogd  PSIG  SIGPIPE/ => 0,
            qr/syslogd  RET   execve 0/ => 1,
        },
index 93032fe..ef3d62b 100644 (file)
@@ -18,8 +18,7 @@ our %args = (
        loggrep => { get_between2loggrep() },
     },
     syslogd => {
-       ktrace => 1,
-       kdump => {
+       ktrace => {
            qr/syslogd  PSIG  SIGTERM caught handler/ => 1,
            qr/syslogd  RET   execve 0/ => 1,
        },
index 13429a6..1db665a 100644 (file)
@@ -11,18 +11,15 @@ use Socket;
 
 our %args = (
     syslogd => {
-       fstat => 1,
+       fstat => {
+           qr/ internet stream tcp / => 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 67faf5e..850fadf 100644 (file)
@@ -11,18 +11,15 @@ use Socket;
 
 our %args = (
     syslogd => {
-       fstat => 1,
+       fstat => {
+           qr/ internet stream tcp / => 1,
+       },
        loghost => '@tls://127.0.0.1:$connectport',
        options => ["-n"],
     },
     server => {
        listen => { domain => AF_INET, addr => "127.0.0.1", proto => "tls" },
     },
-    fstat => {
-       loggrep => {
-           qr/ internet stream tcp / => 1,
-       },
-    },
 );
 
 1;
index afb4865..2903cf6 100644 (file)
@@ -15,14 +15,11 @@ our %args = (
        connect => { domain => AF_INET, addr => "127.0.0.1", port => 514 },
     },
     syslogd => {
-       fstat => 1,
-       options => ["-nu"],
-    },
-    fstat => {
-       loggrep => {
+       fstat => {
            qr/ internet dgram udp \*:514$/ => 1,
            qr/ internet6 dgram udp \*:514$/ => 1,
        },
+       options => ["-nu"],
     },
 );
 
index 4f71b52..a30d97e 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: funcs.pl,v 1.18 2015/02/12 23:16:02 bluhm Exp $
+#      $OpenBSD: funcs.pl,v 1.19 2015/06/15 21:44:57 bluhm Exp $
 
 # Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org>
 #
@@ -248,8 +248,8 @@ sub check_logs {
 
        check_log($c, $r, $s, @$m);
        check_out($r, %args);
-       check_stat($r, %args);
-       check_kdump($c, $r, $s);
+       check_fstat($c, $r, $s);
+       check_ktrace($c, $r, $s);
        if (my $file = $s->{"outfile"}) {
                my $pattern = $s->{filegrep} || $testlog;
                check_pattern(ref $s, $file, $pattern, \&filegrep);
@@ -323,14 +323,11 @@ sub check_out {
        }
 }
 
-sub check_stat {
-       my ($r, %args) = @_;
-
-       foreach my $name (qw(fstat)) {
-               next unless $r && $r->{$name};
-               my $file = $r->{"${name}file"} or die;
-               my $pattern = $args{$name}{loggrep} or die;
-               check_pattern($name, $file, $pattern, \&filegrep);
+sub check_fstat {
+       foreach my $proc (@_) {
+               my $pattern = $proc && $proc->{fstat} or next;
+               my $file = $proc->{fstatfile} or die;
+               check_pattern("fstat", $file, $pattern, \&filegrep);
        }
 }
 
@@ -343,12 +340,11 @@ sub filegrep {
            grep { /$pattern/ } <$fh> : first { /$pattern/ } <$fh>;
 }
 
-sub check_kdump {
+sub check_ktrace {
        foreach my $proc (@_) {
-               next unless $proc && $proc->{ktrace};
+               my $pattern = $proc && $proc->{ktrace} or next;
                my $file = $proc->{ktracefile} or die;
-               my $pattern = $proc->{kdump} or die;
-               check_pattern(ref $proc, $file, $pattern, \&kdumpgrep);
+               check_pattern("ktrace", $file, $pattern, \&kdumpgrep);
        }
 }