access-engine/internal/emission/lock_linux.go
tegwick 0a05383195
Some checks failed
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s
Build and Publish Container Image / build-and-push (push) Failing after 1m1s
Bound durable outbox storage and enforce process writer exclusion
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
2026-10-16 18:43:52 +02:00

44 lines
1.3 KiB
Go

//go:build linux
package emission
import (
"errors"
"os"
"syscall"
)
func acquireWriterLock(path string) (*os.File, error) {
file, err := openOwnedFile(path, os.O_CREATE|os.O_RDWR, 0600)
if err != nil {
return nil, err
}
if err := syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
file.Close()
return nil, errors.New("outbox already has a writer or filesystem lock unavailable")
}
return file, nil
}
func infoSys(info os.FileInfo) (*syscall.Stat_t, bool) {
if info == nil {
return nil, false
}
stat, ok := info.Sys().(*syscall.Stat_t)
return stat, ok
}
// Shared journal/cursor aliases must not evade directory-based exclusion.
// Nonblocking open also rejects unexpected FIFOs/devices without waiting.
func openOwnedFile(path string, flags int, mode os.FileMode) (*os.File, error) {
file, err := os.OpenFile(path, flags|syscall.O_NOFOLLOW|syscall.O_NONBLOCK, mode)
if err != nil {
return nil, err
}
info, err := file.Stat()
stat, ok := infoSys(info)
if err != nil || !ok || !info.Mode().IsRegular() || info.Mode().Perm()&0007 != 0 || stat.Nlink != 1 || stat.Uid != uint32(os.Geteuid()) || (info.Mode().Perm()&0070 != 0 && stat.Gid != uint32(os.Getegid())) {
file.Close()
return nil, errors.New("outbox file must be a single-link owner/current-group regular file")
}
return file, nil
}