helper: expose extra files to direct
Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
0f1f0e4364
commit
10a21ce3ef
@ -10,6 +10,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/helper"
|
"git.gensokyo.uk/security/fortify/helper"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
||||||
@ -40,13 +41,14 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error
|
|||||||
c, cancel := context.WithCancelCause(ctx)
|
c, cancel := context.WithCancelCause(ctx)
|
||||||
if !sandbox {
|
if !sandbox {
|
||||||
h = helper.NewDirect(c, p.name, p.seal, true, argF, func(cmd *exec.Cmd) {
|
h = helper.NewDirect(c, p.name, p.seal, true, argF, func(cmd *exec.Cmd) {
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||||
if output != nil {
|
if output != nil {
|
||||||
cmd.Stdout, cmd.Stderr = output, output
|
cmd.Stdout, cmd.Stderr = output, output
|
||||||
}
|
}
|
||||||
|
|
||||||
// xdg-dbus-proxy does not need to inherit the environment
|
// xdg-dbus-proxy does not need to inherit the environment
|
||||||
cmd.Env = make([]string, 0)
|
cmd.Env = make([]string, 0)
|
||||||
})
|
}, nil)
|
||||||
} else {
|
} else {
|
||||||
// look up absolute path if name is just a file name
|
// look up absolute path if name is just a file name
|
||||||
toolPath := p.name
|
toolPath := p.name
|
||||||
@ -117,10 +119,11 @@ func (p *Proxy) Start(ctx context.Context, output io.Writer, sandbox bool) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
h = helper.MustNewBwrap(c, toolPath, p.seal, true, argF, func(cmd *exec.Cmd) {
|
h = helper.MustNewBwrap(c, toolPath, p.seal, true, argF, func(cmd *exec.Cmd) {
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||||
if output != nil {
|
if output != nil {
|
||||||
cmd.Stdout, cmd.Stderr = output, output
|
cmd.Stdout, cmd.Stderr = output, output
|
||||||
}
|
}
|
||||||
}, bc, true, nil, nil)
|
}, nil, bc, nil)
|
||||||
p.bwrap = bc
|
p.bwrap = bc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
||||||
"git.gensokyo.uk/security/fortify/helper/proc"
|
"git.gensokyo.uk/security/fortify/helper/proc"
|
||||||
@ -26,12 +25,11 @@ func MustNewBwrap(
|
|||||||
stat bool,
|
stat bool,
|
||||||
argF func(argsFd, statFd int) []string,
|
argF func(argsFd, statFd int) []string,
|
||||||
cmdF func(cmd *exec.Cmd),
|
cmdF func(cmd *exec.Cmd),
|
||||||
conf *bwrap.Config,
|
|
||||||
setpgid bool,
|
|
||||||
extraFiles []*os.File,
|
extraFiles []*os.File,
|
||||||
|
conf *bwrap.Config,
|
||||||
syncFd *os.File,
|
syncFd *os.File,
|
||||||
) Helper {
|
) Helper {
|
||||||
b, err := NewBwrap(ctx, name, wt, stat, argF, cmdF, conf, setpgid, extraFiles, syncFd)
|
b, err := NewBwrap(ctx, name, wt, stat, argF, cmdF, extraFiles, conf, syncFd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
} else {
|
} else {
|
||||||
@ -49,15 +47,11 @@ func NewBwrap(
|
|||||||
stat bool,
|
stat bool,
|
||||||
argF func(argsFd, statFd int) []string,
|
argF func(argsFd, statFd int) []string,
|
||||||
cmdF func(cmd *exec.Cmd),
|
cmdF func(cmd *exec.Cmd),
|
||||||
conf *bwrap.Config,
|
|
||||||
setpgid bool,
|
|
||||||
extraFiles []*os.File,
|
extraFiles []*os.File,
|
||||||
|
conf *bwrap.Config,
|
||||||
syncFd *os.File,
|
syncFd *os.File,
|
||||||
) (Helper, error) {
|
) (Helper, error) {
|
||||||
b, args := newHelperCmd(ctx, BubblewrapName, wt, stat, argF, extraFiles)
|
b, args := newHelperCmd(ctx, BubblewrapName, wt, stat, argF, extraFiles)
|
||||||
if setpgid {
|
|
||||||
b.Cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
var argsFd uintptr
|
var argsFd uintptr
|
||||||
if v, err := NewCheckedArgs(conf.Args(syncFd, b.extraFiles, &b.files)); err != nil {
|
if v, err := NewCheckedArgs(conf.Args(syncFd, b.extraFiles, &b.files)); err != nil {
|
||||||
|
@ -36,7 +36,8 @@ func TestBwrap(t *testing.T) {
|
|||||||
"fortify",
|
"fortify",
|
||||||
argsWt, false,
|
argsWt, false,
|
||||||
argF, nil,
|
argF, nil,
|
||||||
sc, false, nil, nil,
|
nil,
|
||||||
|
sc, nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := h.Start(); !errors.Is(err, os.ErrNotExist) {
|
if err := h.Start(); !errors.Is(err, os.ErrNotExist) {
|
||||||
@ -51,7 +52,8 @@ func TestBwrap(t *testing.T) {
|
|||||||
"fortify",
|
"fortify",
|
||||||
argsWt, false,
|
argsWt, false,
|
||||||
argF, nil,
|
argF, nil,
|
||||||
sc, false, nil, nil,
|
nil,
|
||||||
|
sc, nil,
|
||||||
); got == nil {
|
); got == nil {
|
||||||
t.Errorf("MustNewBwrap(%#v, %#v, %#v) got nil",
|
t.Errorf("MustNewBwrap(%#v, %#v, %#v) got nil",
|
||||||
sc, argsWt, "fortify")
|
sc, argsWt, "fortify")
|
||||||
@ -73,7 +75,8 @@ func TestBwrap(t *testing.T) {
|
|||||||
"fortify",
|
"fortify",
|
||||||
argsWt, false,
|
argsWt, false,
|
||||||
argF, nil,
|
argF, nil,
|
||||||
&bwrap.Config{Hostname: "\x00"}, false, nil, nil,
|
nil,
|
||||||
|
&bwrap.Config{Hostname: "\x00"}, nil,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -87,7 +90,8 @@ func TestBwrap(t *testing.T) {
|
|||||||
ctx, "crash-test-dummy",
|
ctx, "crash-test-dummy",
|
||||||
nil, false,
|
nil, false,
|
||||||
argFChecked, func(cmd *exec.Cmd) { cmd.Stdout, cmd.Stderr = stdout, stderr },
|
argFChecked, func(cmd *exec.Cmd) { cmd.Stdout, cmd.Stderr = stdout, stderr },
|
||||||
sc, false, nil, nil,
|
nil,
|
||||||
|
sc, nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := h.Start(); err != nil {
|
if err := h.Start(); err != nil {
|
||||||
@ -108,7 +112,8 @@ func TestBwrap(t *testing.T) {
|
|||||||
ctx, "crash-test-dummy",
|
ctx, "crash-test-dummy",
|
||||||
argsWt, stat,
|
argsWt, stat,
|
||||||
argF, cmdF,
|
argF, cmdF,
|
||||||
sc, false, nil, nil,
|
nil,
|
||||||
|
sc, nil,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -22,8 +22,9 @@ func NewDirect(
|
|||||||
stat bool,
|
stat bool,
|
||||||
argF func(argsFd, statFd int) []string,
|
argF func(argsFd, statFd int) []string,
|
||||||
cmdF func(cmd *exec.Cmd),
|
cmdF func(cmd *exec.Cmd),
|
||||||
|
extraFiles []*os.File,
|
||||||
) Helper {
|
) Helper {
|
||||||
d, args := newHelperCmd(ctx, name, wt, stat, argF, nil)
|
d, args := newHelperCmd(ctx, name, wt, stat, argF, extraFiles)
|
||||||
d.Args = append(d.Args, args...)
|
d.Args = append(d.Args, args...)
|
||||||
if cmdF != nil {
|
if cmdF != nil {
|
||||||
cmdF(d.Cmd)
|
cmdF(d.Cmd)
|
||||||
@ -54,24 +55,6 @@ type helperCmd struct {
|
|||||||
*exec.Cmd
|
*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 {
|
func (h *helperCmd) Start() error {
|
||||||
h.mu.Lock()
|
h.mu.Lock()
|
||||||
defer h.mu.Unlock()
|
defer h.mu.Unlock()
|
||||||
@ -82,6 +65,20 @@ func (h *helperCmd) Start() error {
|
|||||||
return errors.New("exec: already started")
|
return errors.New("exec: already started")
|
||||||
}
|
}
|
||||||
|
|
||||||
h.finalise()
|
h.Env = slices.Grow(h.Env, 2)
|
||||||
|
if h.useArgsFd {
|
||||||
|
h.Env = append(h.Env, FortifyHelper+"=1")
|
||||||
|
} else {
|
||||||
|
h.Env = append(h.Env, FortifyHelper+"=0")
|
||||||
|
}
|
||||||
|
if h.useStatFd {
|
||||||
|
h.Env = append(h.Env, FortifyStatus+"=1")
|
||||||
|
|
||||||
|
// stat is populated on fulfill
|
||||||
|
h.Cancel = func() error { return h.stat.Close() }
|
||||||
|
} else {
|
||||||
|
h.Env = append(h.Env, FortifyStatus+"=0")
|
||||||
|
}
|
||||||
|
|
||||||
return proc.Fulfill(h.helperFiles.ctx, &h.ExtraFiles, h.Cmd.Start, h.files, h.extraFiles)
|
return proc.Fulfill(h.helperFiles.ctx, &h.ExtraFiles, h.Cmd.Start, h.files, h.extraFiles)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
func TestDirect(t *testing.T) {
|
func TestDirect(t *testing.T) {
|
||||||
t.Run("start non-existent helper path", func(t *testing.T) {
|
t.Run("start non-existent helper path", func(t *testing.T) {
|
||||||
h := helper.NewDirect(context.Background(), "/nonexistent", argsWt, false, argF, nil)
|
h := helper.NewDirect(context.Background(), "/nonexistent", argsWt, false, argF, nil, nil)
|
||||||
|
|
||||||
if err := h.Start(); !errors.Is(err, os.ErrNotExist) {
|
if err := h.Start(); !errors.Is(err, os.ErrNotExist) {
|
||||||
t.Errorf("Start: error = %v, wantErr %v",
|
t.Errorf("Start: error = %v, wantErr %v",
|
||||||
@ -21,7 +21,7 @@ func TestDirect(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("valid new helper nil check", func(t *testing.T) {
|
t.Run("valid new helper nil check", func(t *testing.T) {
|
||||||
if got := helper.NewDirect(context.TODO(), "fortify", argsWt, false, argF, nil); got == nil {
|
if got := helper.NewDirect(context.TODO(), "fortify", argsWt, false, argF, nil, nil); got == nil {
|
||||||
t.Errorf("New(%q, %q) got nil",
|
t.Errorf("New(%q, %q) got nil",
|
||||||
argsWt, "fortify")
|
argsWt, "fortify")
|
||||||
return
|
return
|
||||||
@ -30,7 +30,7 @@ func TestDirect(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("implementation compliance", func(t *testing.T) {
|
t.Run("implementation compliance", func(t *testing.T) {
|
||||||
testHelper(t, func(ctx context.Context, cmdF func(cmd *exec.Cmd), stat bool) helper.Helper {
|
testHelper(t, func(ctx context.Context, cmdF func(cmd *exec.Cmd), stat bool) helper.Helper {
|
||||||
return helper.NewDirect(ctx, "crash-test-dummy", argsWt, stat, argF, cmdF)
|
return helper.NewDirect(ctx, "crash-test-dummy", argsWt, stat, argF, cmdF, nil)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,8 @@ func Main() {
|
|||||||
nil, false,
|
nil, false,
|
||||||
func(int, int) []string { return make([]string, 0) },
|
func(int, int) []string { return make([]string, 0) },
|
||||||
func(cmd *exec.Cmd) { cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr },
|
func(cmd *exec.Cmd) { cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr },
|
||||||
conf, false, extraFiles, syncFd,
|
extraFiles,
|
||||||
|
conf, syncFd,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Fatalf("malformed sandbox config: %v", err)
|
log.Fatalf("malformed sandbox config: %v", err)
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user