mirror of
https://github.com/criyle/go-sandbox.git
synced 2025-11-04 14:49:53 +08:00
94 lines
2.4 KiB
Go
94 lines
2.4 KiB
Go
package deamon
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/criyle/go-sandbox/forkexec"
|
|
"github.com/criyle/go-sandbox/memfd"
|
|
"github.com/criyle/go-sandbox/unixsocket"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// Master manages single pre-forked container
|
|
type Master struct {
|
|
pid int // underlying container init pid
|
|
socket *unixsocket.Socket // master - container communication
|
|
}
|
|
|
|
// New creates new master with underlying container
|
|
func New(root string) (*Master, error) {
|
|
// dummy stdin / stdout / stderr
|
|
fnull, err := os.OpenFile(os.DevNull, os.O_RDWR, 0666)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("deamon: failed to open devNull(%v)", err)
|
|
}
|
|
defer fnull.Close()
|
|
|
|
// prepare self memfd
|
|
self, err := os.Open("/proc/self/exe")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("deamon: failed to open /proc/self/exe(%v)", err)
|
|
}
|
|
defer self.Close()
|
|
|
|
execFile, err := memfd.DupToMemfd("deamon", self)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("deamon: failed to create memfd(%v)", err)
|
|
}
|
|
defer execFile.Close()
|
|
|
|
// prepare socket
|
|
ins, outs, err := unixsocket.NewSocketPair()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("deamon: failed to create socket(%v)", err)
|
|
}
|
|
outf, err := outs.Conn.File()
|
|
if err != nil {
|
|
ins.Conn.Close()
|
|
outs.Conn.Close()
|
|
return nil, fmt.Errorf("deamon: failed to dup file outs(%v)", err)
|
|
}
|
|
defer outf.Close()
|
|
if err = ins.SetPassCred(1); err != nil {
|
|
ins.Conn.Close()
|
|
outs.Conn.Close()
|
|
return nil, fmt.Errorf("deamon: failed to set pass_cred ins(%v)", err)
|
|
}
|
|
if err = outs.SetPassCred(1); err != nil {
|
|
ins.Conn.Close()
|
|
outs.Conn.Close()
|
|
return nil, fmt.Errorf("deamon: failed to set pass_cred outs(%v)", err)
|
|
}
|
|
|
|
r := &forkexec.Runner{
|
|
Args: []string{os.Args[0], initArg},
|
|
Env: []string{DefaultPath},
|
|
ExecFile: execFile.Fd(),
|
|
Files: []uintptr{fnull.Fd(), fnull.Fd(), fnull.Fd(), uintptr(outf.Fd())},
|
|
WorkDir: "/w",
|
|
UnshareFlags: forkexec.UnshareFlags,
|
|
Mounts: DefaultMounts,
|
|
HostName: "deamon",
|
|
DomainName: "deamon",
|
|
PivotRoot: root,
|
|
}
|
|
pid, err := r.Start()
|
|
if err != nil {
|
|
ins.Conn.Close()
|
|
outs.Conn.Close()
|
|
return nil, fmt.Errorf("deamon: failed to execve(%v)", err)
|
|
}
|
|
|
|
outs.Conn.Close()
|
|
return &Master{pid, ins}, nil
|
|
}
|
|
|
|
// Destroy kill the deamon process (with container)
|
|
func (m *Master) Destroy() error {
|
|
var wstatus unix.WaitStatus
|
|
unix.Kill(m.pid, unix.SIGKILL)
|
|
_, err := unix.Wait4(m.pid, &wstatus, 0, nil)
|
|
return err
|
|
}
|