helper: combine helper ipc setup
The two-step args call is no longer necessary since stat is passed on initialisation. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
87
helper/cmd.go
Normal file
87
helper/cmd.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"slices"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/helper/proc"
|
||||
)
|
||||
|
||||
// NewDirect initialises a new direct Helper instance with wt as the null-terminated argument writer.
|
||||
// Function argF returns an array of arguments passed directly to the child process.
|
||||
func NewDirect(
|
||||
ctx context.Context,
|
||||
name string,
|
||||
wt io.WriterTo,
|
||||
stat bool,
|
||||
argF func(argsFd, statFd int) []string,
|
||||
cmdF func(cmd *exec.Cmd),
|
||||
) Helper {
|
||||
d, args := newHelperCmd(ctx, name, wt, stat, argF, nil)
|
||||
d.Args = append(d.Args, args...)
|
||||
if cmdF != nil {
|
||||
cmdF(d.Cmd)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func newHelperCmd(
|
||||
ctx context.Context,
|
||||
name string,
|
||||
wt io.WriterTo,
|
||||
stat bool,
|
||||
argF func(argsFd, statFd int) []string,
|
||||
extraFiles []*os.File,
|
||||
) (cmd *helperCmd, args []string) {
|
||||
cmd = new(helperCmd)
|
||||
cmd.helperFiles, args = newHelperFiles(ctx, wt, stat, argF, extraFiles)
|
||||
cmd.Cmd = commandContext(ctx, name)
|
||||
cmd.Cmd.Cancel = func() error { return cmd.Process.Signal(syscall.SIGTERM) }
|
||||
cmd.WaitDelay = WaitDelay
|
||||
return
|
||||
}
|
||||
|
||||
// helperCmd provides a [exec.Cmd] wrapper around helper ipc.
|
||||
type helperCmd struct {
|
||||
mu sync.RWMutex
|
||||
*helperFiles
|
||||
*exec.Cmd
|
||||
}
|
||||
|
||||
// finalise sets up the underlying [exec.Cmd] object.
|
||||
func (h *helperCmd) finalise() {
|
||||
h.Env = slices.Grow(h.Env, 2)
|
||||
if h.useArgsFd {
|
||||
h.Cmd.Env = append(h.Env, FortifyHelper+"=1")
|
||||
} else {
|
||||
h.Cmd.Env = append(h.Env, FortifyHelper+"=0")
|
||||
}
|
||||
if h.useStatFd {
|
||||
h.Cmd.Env = append(h.Cmd.Env, FortifyStatus+"=1")
|
||||
|
||||
// stat is populated on fulfill
|
||||
h.Cmd.Cancel = func() error { return h.stat.Close() }
|
||||
} else {
|
||||
h.Cmd.Env = append(h.Cmd.Env, FortifyStatus+"=0")
|
||||
}
|
||||
}
|
||||
|
||||
func (h *helperCmd) Start() error {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
|
||||
// Check for doubled Start calls before we defer failure cleanup. If the prior
|
||||
// call to Start succeeded, we don't want to spuriously close its pipes.
|
||||
if h.Cmd != nil && h.Cmd.Process != nil {
|
||||
return errors.New("exec: already started")
|
||||
}
|
||||
|
||||
h.finalise()
|
||||
return proc.Fulfill(h.helperFiles.ctx, &h.ExtraFiles, h.Cmd.Start, h.files, h.extraFiles)
|
||||
}
|
||||
Reference in New Issue
Block a user