Confine subprocess diagnostics and retain redacted tails
This commit is contained in:
@@ -18,6 +18,7 @@ const (
|
||||
MaxStdoutDiagnosticBytes int64 = 8 * 1024 * 1024
|
||||
// MaxStderrDiagnosticBytes bounds persisted stderr from one external command.
|
||||
MaxStderrDiagnosticBytes int64 = 8 * 1024 * 1024
|
||||
diagnosticTailBytes = 2048
|
||||
)
|
||||
|
||||
var inheritedEnvironmentNames = map[string]struct{}{
|
||||
@@ -87,6 +88,7 @@ type diagnosticWriter struct {
|
||||
received int64
|
||||
persisted int64
|
||||
redactor streamRedactor
|
||||
tail []byte
|
||||
}
|
||||
|
||||
func openLogWriters(stdoutPath, stderrPath, owner string, sensitiveValues []string) (*logWriters, error) {
|
||||
@@ -169,6 +171,7 @@ func (w *diagnosticWriter) writeRedacted(data []byte) error {
|
||||
}
|
||||
written, err := w.target.Write(toWrite)
|
||||
w.persisted += int64(written)
|
||||
w.retainTail(toWrite[:written])
|
||||
w.logs.mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -179,6 +182,34 @@ func (w *diagnosticWriter) writeRedacted(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *diagnosticWriter) Tail() string {
|
||||
w.logs.mu.Lock()
|
||||
defer w.logs.mu.Unlock()
|
||||
return strings.TrimSpace(string(w.tail))
|
||||
}
|
||||
|
||||
func (w *diagnosticWriter) retainTail(data []byte) {
|
||||
if len(data) >= diagnosticTailBytes {
|
||||
if cap(w.tail) < diagnosticTailBytes {
|
||||
w.tail = make([]byte, diagnosticTailBytes)
|
||||
} else {
|
||||
w.tail = w.tail[:diagnosticTailBytes]
|
||||
}
|
||||
copy(w.tail, data[len(data)-diagnosticTailBytes:])
|
||||
return
|
||||
}
|
||||
if cap(w.tail) < diagnosticTailBytes {
|
||||
retained := make([]byte, len(w.tail), diagnosticTailBytes)
|
||||
copy(retained, w.tail)
|
||||
w.tail = retained
|
||||
}
|
||||
if overflow := len(w.tail) + len(data) - diagnosticTailBytes; overflow > 0 {
|
||||
copy(w.tail, w.tail[overflow:])
|
||||
w.tail = w.tail[:len(w.tail)-overflow]
|
||||
}
|
||||
w.tail = append(w.tail, data...)
|
||||
}
|
||||
|
||||
func (w *diagnosticWriter) reachLimit() error {
|
||||
limit := &captureLimitError{stream: w.stream, owner: w.owner, limit: w.limit}
|
||||
w.logs.mu.Lock()
|
||||
@@ -224,7 +255,7 @@ func openDiagnosticFile(path string) (*os.File, error) {
|
||||
if err := fileops.EnsureWorkspaceDirectory(filepath.Dir(path)); err != nil {
|
||||
return nil, fmt.Errorf("create log directory for %q: %w", path, err)
|
||||
}
|
||||
file, err := os.Create(path)
|
||||
file, err := fileops.OpenFileConfined(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileops.WorkspaceFileMode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open log file %q: %w", path, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user