From: bluhm Date: Thu, 1 Jan 2015 19:58:48 +0000 (+0000) Subject: Test that syslogd sending over TCP does not leak a file descriptor X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=7500daf11e27dbc0c8e712616174d5cc753eb730;p=openbsd Test that syslogd sending over TCP does not leak a file descriptor when it receives a SIGHUP. --- diff --git a/regress/usr.sbin/syslogd/LICENSE b/regress/usr.sbin/syslogd/LICENSE index a6e1dd38fcf..407681ad0a6 100644 --- a/regress/usr.sbin/syslogd/LICENSE +++ b/regress/usr.sbin/syslogd/LICENSE @@ -1,4 +1,4 @@ -# Copyright (c) 2010-2014 Alexander Bluhm +# Copyright (c) 2010-2015 Alexander Bluhm # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above diff --git a/regress/usr.sbin/syslogd/Proc.pm b/regress/usr.sbin/syslogd/Proc.pm index 46d70019e7a..37280ee651d 100644 --- a/regress/usr.sbin/syslogd/Proc.pm +++ b/regress/usr.sbin/syslogd/Proc.pm @@ -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 +# Copyright (c) 2010-2015 Alexander Bluhm # Copyright (c) 2014 Florian Riehm # # 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); diff --git a/regress/usr.sbin/syslogd/Syslogd.pm b/regress/usr.sbin/syslogd/Syslogd.pm index b70a8eafd5c..bc233082424 100644 --- a/regress/usr.sbin/syslogd/Syslogd.pm +++ b/regress/usr.sbin/syslogd/Syslogd.pm @@ -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 +# Copyright (c) 2010-2015 Alexander Bluhm # Copyright (c) 2014 Florian Riehm # # 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 index 00000000000..0a31dbd3fcf --- /dev/null +++ b/regress/usr.sbin/syslogd/args-sighup-tcp.pl @@ -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; diff --git a/regress/usr.sbin/syslogd/args-sighup.pl b/regress/usr.sbin/syslogd/args-sighup.pl index 63ffe2cac4c..b375ebbabf8 100644 --- a/regress/usr.sbin/syslogd/args-sighup.pl +++ b/regress/usr.sbin/syslogd/args-sighup.pl @@ -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 index 00000000000..cbd8bee3427 --- /dev/null +++ b/regress/usr.sbin/syslogd/args-socket-tcp.pl @@ -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; diff --git a/regress/usr.sbin/syslogd/funcs.pl b/regress/usr.sbin/syslogd/funcs.pl index d71d73bbcc9..382ab1f8f70 100644 --- a/regress/usr.sbin/syslogd/funcs.pl +++ b/regress/usr.sbin/syslogd/funcs.pl @@ -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 +# Copyright (c) 2010-2015 Alexander Bluhm # # 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/;