bastion 0.54.0
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
//go:build !windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log/syslog"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestAuditRowsDoNotWaitOnAStuckSyslogSocket: a real syslog writer on a
|
||||
// datagram socket nobody reads blocks once the socket's queue is full, as
|
||||
// /dev/log does while journald is stuck. Audit rows behind the queue all
|
||||
// return at once; the same writer called inline (as 0.54.0 first did) does not.
|
||||
func TestAuditRowsDoNotWaitOnAStuckSyslogSocket(t *testing.T) {
|
||||
dir, err := os.MkdirTemp("", "al")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { os.RemoveAll(dir) })
|
||||
sock := filepath.Join(dir, "s")
|
||||
l, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Name: sock, Net: "unixgram"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Closing the reading end is what lets the stuck writes below return
|
||||
// (refused) so their goroutines end; the writer itself is never closed,
|
||||
// since its Close would wait behind a write that is stuck.
|
||||
t.Cleanup(func() { l.Close() })
|
||||
w, err := syslog.Dial("unixgram", sock, syslog.LOG_AUTH|syslog.LOG_INFO, auditSyslogTag)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
write := func(line []byte) { _ = w.Info(string(line)) }
|
||||
|
||||
// The inline writer does block: without this the test proves nothing.
|
||||
inline := make(chan struct{})
|
||||
go func() {
|
||||
for i := 0; i < 5000; i++ {
|
||||
write([]byte(`{"op":"x"}`))
|
||||
}
|
||||
close(inline)
|
||||
}()
|
||||
select {
|
||||
case <-inline:
|
||||
t.Skip("this kernel never blocked a datagram writer; nothing to bound")
|
||||
case <-time.After(2 * time.Second):
|
||||
}
|
||||
|
||||
q := newAuditQueue(64, write)
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
for i := 0; i < 5000; i++ {
|
||||
q.enqueue([]byte(`{"op":"y"}`))
|
||||
}
|
||||
close(done)
|
||||
}()
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("audit rows waited on a stuck syslog socket")
|
||||
}
|
||||
if q.dropped.Load() == 0 {
|
||||
t.Fatal("rows past the bound must be counted as dropped")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user