TENTATIVE: Added support for multiple executable for a single profile - Some minor cleanup

master
xSmurf 9 years ago
parent 8f7e81d5f9
commit 154c8ac5e9

@ -43,6 +43,13 @@ func main() {
},
}
flagsForce := []cli.Flag{
cli.BoolFlag{
Name: "force, f",
Usage: "Force the command to run through non fatal errors",
},
}
app.Commands = []cli.Command{
{
Name: "config",
@ -64,13 +71,13 @@ func main() {
Name: "install",
Usage: "install binary diversion for a program",
Action: handleInstall,
Flags: flagsHookMode,
Flags: append(flagsForce, flagsHookMode...),
},
{
Name: "remove",
Usage: "remove a binary diversion for a program",
Action: handleRemove,
Flags: flagsHookMode,
Flags: append(flagsForce, flagsHookMode...),
},
{
Name: "status",
@ -147,8 +154,8 @@ func handleConfigshow(c *cli.Context) {
fmt.Printf(hfmt, "Config file", "Not found - using defaults")
}
for i := 0; i < len(fmt.Sprintf(sfmt, "", "")); i++ {
fmt.Print("=")
for i := 0; i < len(fmt.Sprintf(sfmt, "", ""))+2; i++ {
fmt.Print("#")
}
fmt.Println("")
@ -180,39 +187,52 @@ func handleInstall(c *cli.Context) {
return // For clarity
}
isInstalled, err := isDivertInstalled(OzProfile.Path)
if err != nil {
fmt.Fprintf(os.Stderr, "Unknown error: %+v\n", err)
os.Exit(1)
}
if isInstalled == true {
fmt.Println("Divert already installed for ", OzProfile.Path)
os.Exit(0)
}
divertInstall := func(cpath string) {
isInstalled, err := isDivertInstalled(cpath)
if err != nil {
fmt.Fprintf(os.Stderr, "Unknown error: %+v\n", err)
os.Exit(1)
}
if isInstalled == true {
fmt.Println("Divert already installed for ", cpath)
if c.Bool("force") {
return
}
os.Exit(0)
}
dpkgArgs := []string{
"--add",
"--package",
"oz",
"--rename",
"--divert",
getBinaryPath(OzProfile.Path),
OzProfile.Path,
}
dpkgArgs := []string{
"--add",
"--package",
"oz",
"--rename",
"--divert",
getBinaryPath(cpath),
cpath,
}
_, err = exec.Command(PathDpkgDivert, dpkgArgs...).Output()
if err != nil {
fmt.Fprintf(os.Stderr, "Dpkg divert command `%s %+s` failed: %s", PathDpkgDivert, dpkgArgs, err)
os.Exit(1)
_, err = exec.Command(PathDpkgDivert, dpkgArgs...).Output()
if err != nil {
fmt.Fprintf(os.Stderr, "Dpkg divert command `%s %+s` failed: %s", PathDpkgDivert, dpkgArgs, err)
os.Exit(1)
}
err = syscall.Symlink(OzConfig.ClientPath, cpath)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create symlink %s", err)
os.Exit(1)
}
fmt.Printf("Successfully installed Oz sandbox for: %s.\n", cpath)
}
err = syscall.Symlink(OzConfig.ClientPath, OzProfile.Path)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create symlink %s", err)
os.Exit(1)
paths := append([]string{}, OzProfile.Path)
paths = append(paths, OzProfile.Paths...)
for _, pp := range paths {
divertInstall(pp)
}
fmt.Printf("Successfully installed Oz sandbox for: %s.\n", OzProfile.Path)
fmt.Printf("Successfully installed Oz sandbox for: %s.\n", OzProfile.Name)
}
func handleRemove(c *cli.Context) {
@ -229,33 +249,46 @@ func handleRemove(c *cli.Context) {
return // For clarity
}
isInstalled, err := isDivertInstalled(OzProfile.Path)
if err != nil {
fmt.Fprintf(os.Stderr, "Unknown error: %+v\n", err)
os.Exit(1)
}
if isInstalled == false {
fmt.Println("Divert is not installed for ", OzProfile.Path)
os.Exit(0)
}
divertRemove := func(cpath string) {
isInstalled, err := isDivertInstalled(cpath)
if err != nil {
fmt.Fprintf(os.Stderr, "Unknown error: %+v\n", err)
os.Exit(1)
}
if isInstalled == false {
fmt.Println("Divert is not installed for ", cpath)
if c.Bool("force") {
return
}
os.Exit(0)
}
os.Remove(cpath)
dpkgArgs := []string{
"--rename",
"--package",
"oz",
"--remove",
cpath,
}
os.Remove(OzProfile.Path)
_, err = exec.Command(PathDpkgDivert, dpkgArgs...).Output()
if err != nil {
fmt.Fprintf(os.Stderr, "Dpkg divert command `%s %+s` failed: %s", PathDpkgDivert, dpkgArgs, err)
os.Exit(1)
}
dpkgArgs := []string{
"--rename",
"--package",
"oz",
"--remove",
OzProfile.Path,
fmt.Printf("Successfully remove jail for: %s.\n", cpath)
}
_, err = exec.Command(PathDpkgDivert, dpkgArgs...).Output()
if err != nil {
fmt.Fprintf(os.Stderr, "Dpkg divert command `%s %+s` failed: %s", PathDpkgDivert, dpkgArgs, err)
os.Exit(1)
paths := append([]string{}, OzProfile.Path)
paths = append(paths, OzProfile.Paths...)
for _, pp := range paths {
divertRemove(pp)
}
fmt.Printf("Successfully remove jail for: %s.\n", OzProfile.Path)
fmt.Printf("Successfully remove jail for: %s.\n", OzProfile.Name)
}
func handleStatus(c *cli.Context) {
@ -263,7 +296,7 @@ func handleStatus(c *cli.Context) {
pname := c.Args()[0]
OzProfile, err := loadProfile(pname, OzConfig.ProfileDir)
if err != nil || OzProfile == nil {
fmt.Fprintf(os.Stderr, "Unable to load profiles (%s).\n", err)
fmt.Fprintf(os.Stderr, "Unable to load profiles (%s): %v.\n", pname, err)
os.Exit(1)
}
@ -272,17 +305,25 @@ func handleStatus(c *cli.Context) {
os.Exit(1)
}
isInstalled, err := isDivertInstalled(OzProfile.Path)
if err != nil {
fmt.Fprintf(os.Stderr, "Unknown error: %+v\n", err)
os.Exit(1)
}
if isInstalled {
fmt.Println("Package divert is \033[0;32minstalled\033[0m for: ", OzProfile.Path)
} else {
fmt.Println("Package divert is \033[0;31mnot installed\033[0m for: ", OzProfile.Path)
checkInstalled := func(cpath string) {
isInstalled, err := isDivertInstalled(cpath)
if err != nil {
fmt.Fprintf(os.Stderr, "Unknown error: %+v\n", err)
os.Exit(1)
}
sfmt := "%-37s\033[0m%s\n"
if isInstalled {
fmt.Printf("\033[0;32m"+sfmt, "Package divert is installed for: ", cpath)
} else {
fmt.Printf("\033[0;31m"+sfmt, "Package divert is not installed for: ", cpath)
}
}
paths := append([]string{}, OzProfile.Path)
paths = append(paths, OzProfile.Paths...)
for _, pp := range paths {
checkInstalled(pp)
}
}
func handleCreate(c *cli.Context) {
@ -366,10 +407,15 @@ func loadConfig() *oz.Config {
func loadProfile(name, profileDir string) (*oz.Profile, error) {
ps, err := oz.LoadProfiles(profileDir)
if err != nil {
fmt.Println("DERP1")
return nil, err
}
return ps.GetProfileByName(name)
p, err := ps.GetProfileByName(name)
if err != nil || p == nil {
return ps.GetProfileByPath(name)
}
return p, nil
}

@ -18,6 +18,14 @@ const (
ozMaxRandTries = 3
)
type NetType string
const(
TYPE_HOST NetType = "host"
TYPE_EMPTY NetType = "empty"
TYPE_BRIDGE NetType = "bridge"
)
type HostNetwork struct {
// Gateway ip (bridge ip)
Gateway net.IP
@ -35,6 +43,8 @@ type HostNetwork struct {
Max uint64
// Bridge interface MAC Address
BridgeMAC string
//
Nettype NetType
}
type SandboxNetwork struct {
@ -48,6 +58,8 @@ type SandboxNetwork struct {
Gateway net.IP
// IP class (ie: /24)
Class string
//
Nettype NetType
}
var privateNetworkRanges []string

@ -10,17 +10,32 @@ import(
"sync"
"github.com/subgraph/oz/ns"
"github.com/op/go-logging"
)
type ProxyType string
const(
PROXY_CLIENT ProxyType = "client"
PROXY_SERVER ProxyType = "server"
)
type ProtoType string
const(
PROTO_TCP ProtoType = "tcp"
PROTO_UDP ProtoType = "udp"
PROTO_SOCKET ProtoType = "socket"
)
// Socket list, used to hold ports that should be forwarded
type ProxyConfig struct {
// One of client, server
Nettype string `json:"type"`
Nettype ProxyType `json:"type"`
// One of tcp, udp, socket
Proto string
Proto ProtoType
// TCP or UDP port number
Port int
@ -40,12 +55,12 @@ var wgProxy sync.WaitGroup
func ProxySetup(childPid int, ozSockets []ProxyConfig, log *logging.Logger, ready sync.WaitGroup) error {
for _, socket := range ozSockets {
if socket.Nettype == "" || socket.Nettype == "client" {
if socket.Nettype == "" || socket.Nettype == PROXY_CLIENT {
err := newProxyClient(childPid, socket.Proto, socket.Destination, socket.Port, log, ready)
if err != nil {
return fmt.Errorf("Unable to setup client socket forwarding %+v, %s", socket, err)
}
} else if socket.Nettype == "server" {
} else if socket.Nettype == PROXY_SERVER {
err := newProxyServer(childPid, socket.Proto, socket.Destination, socket.Port, log, ready)
if err != nil {
return fmt.Errorf("Unable to setup server socket forwarding %+s, %s", socket, err)
@ -59,8 +74,8 @@ func ProxySetup(childPid int, ozSockets []ProxyConfig, log *logging.Logger, read
/**
* Listener/Client
**/
func proxyClientConn(conn *net.Conn, proto, rAddr string, ready sync.WaitGroup) error {
rConn, err := net.Dial(proto, rAddr)
func proxyClientConn(conn *net.Conn, proto ProtoType, rAddr string, ready sync.WaitGroup) error {
rConn, err := net.Dial(string(proto), rAddr)
if err != nil {
return fmt.Errorf("Socket: %+v.\n", err)
}
@ -71,7 +86,7 @@ func proxyClientConn(conn *net.Conn, proto, rAddr string, ready sync.WaitGroup)
return nil
}
func newProxyClient(pid int, proto, dest string, port int, log *logging.Logger, ready sync.WaitGroup) error {
func newProxyClient(pid int, proto ProtoType, dest string, port int, log *logging.Logger, ready sync.WaitGroup) error {
if dest == "" {
dest = "127.0.0.1"
}
@ -104,7 +119,7 @@ func newProxyClient(pid int, proto, dest string, port int, log *logging.Logger,
return nil
}
func proxySocketListener(pid int, proto, lAddr string) (net.Listener, error) {
func proxySocketListener(pid int, proto ProtoType, lAddr string) (net.Listener, error) {
fd, err := ns.OpenProcess(pid, ns.CLONE_NEWNET)
defer ns.Close(fd)
if err != nil {
@ -114,7 +129,7 @@ func proxySocketListener(pid int, proto, lAddr string) (net.Listener, error) {
return nsSocketListener(fd, proto, lAddr)
}
func nsSocketListener(fd uintptr, proto, lAddr string) (net.Listener, error) {
func nsSocketListener(fd uintptr, proto ProtoType, lAddr string) (net.Listener, error) {
origNs, _ := ns.OpenProcess(os.Getpid(), ns.CLONE_NEWNET)
defer ns.Close(origNs)
defer ns.Set(origNs, ns.CLONE_NEWNET)
@ -124,14 +139,14 @@ func nsSocketListener(fd uintptr, proto, lAddr string) (net.Listener, error) {
return nil, err
}
return net.Listen(proto, lAddr)
return net.Listen(string(proto), lAddr)
}
/**
* Connect/Server
**/
func proxyServerConn(pid int, conn *net.Conn, proto, rAddr string, log *logging.Logger, ready sync.WaitGroup) (error) {
func proxyServerConn(pid int, conn *net.Conn, proto ProtoType, rAddr string, log *logging.Logger, ready sync.WaitGroup) (error) {
rConn, err := socketConnect(pid, proto, rAddr)
if err != nil {
log.Error("Socket: %+v.", err)
@ -144,7 +159,7 @@ func proxyServerConn(pid int, conn *net.Conn, proto, rAddr string, log *logging.
return nil
}
func newProxyServer(pid int, proto, dest string, port int, log *logging.Logger, ready sync.WaitGroup) (error) {
func newProxyServer(pid int, proto ProtoType, dest string, port int, log *logging.Logger, ready sync.WaitGroup) (error) {
if dest == "" {
dest = "127.0.0.1"
}
@ -154,7 +169,7 @@ func newProxyServer(pid int, proto, dest string, port int, log *logging.Logger,
log.Info("Starting socket server forwarding: %s://%s.", proto, lAddr)
listen, err := net.Listen(proto, lAddr)
listen, err := net.Listen(string(proto), lAddr)
if err != nil {
return err
}
@ -177,7 +192,7 @@ func newProxyServer(pid int, proto, dest string, port int, log *logging.Logger,
return nil
}
func socketConnect(pid int, proto, rAddr string) (net.Conn, error) {
func socketConnect(pid int, proto ProtoType, rAddr string) (net.Conn, error) {
fd, err := ns.OpenProcess(pid, ns.CLONE_NEWNET)
defer ns.Close(fd)
if err != nil {
@ -187,7 +202,7 @@ func socketConnect(pid int, proto, rAddr string) (net.Conn, error) {
return nsProxySocketConnect(fd, proto, rAddr)
}
func nsProxySocketConnect(fd uintptr, proto, rAddr string) (net.Conn, error) {
func nsProxySocketConnect(fd uintptr, proto ProtoType, rAddr string) (net.Conn, error) {
origNs, _ := ns.OpenProcess(os.Getpid(), ns.CLONE_NEWNET)
defer ns.Close(origNs)
defer ns.Set(origNs, ns.CLONE_NEWNET)
@ -197,6 +212,6 @@ func nsProxySocketConnect(fd uintptr, proto, rAddr string) (net.Conn, error) {
return nil, err
}
return net.Dial(proto, rAddr)
return net.Dial(string(proto), rAddr)
}

@ -53,7 +53,7 @@ func ListSandboxes() ([]SandboxInfo, error) {
return body.Sandboxes, nil
}
func Launch(arg string, args, env []string, noexec bool) error {
func Launch(arg, cpath string, args, env []string, noexec bool) error {
idx, name, err := parseProfileArg(arg)
if err != nil {
return err
@ -63,6 +63,7 @@ func Launch(arg string, args, env []string, noexec bool) error {
resp, err := clientSend(&LaunchMsg{
Index: idx,
Name: name,
Path: cpath,
Pwd: pwd,
Args: args,
Env: env,

@ -71,7 +71,7 @@ func initialize() *daemonState {
d.nextDisplay = 100
for _, pp := range d.profiles {
if pp.Networking.Nettype == "bridge" {
if pp.Networking.Nettype == network.TYPE_BRIDGE {
d.log.Info("Initializing bridge networking")
htn, err := network.BridgeInit(d.config.BridgeMACAddr, d.config.NMIgnoreFile, d.log)
if err != nil {
@ -127,10 +127,11 @@ func (d *daemonState) handleListProfiles(msg *ListProfilesMsg, m *ipc.Message) e
func (d *daemonState) handleLaunch(msg *LaunchMsg, m *ipc.Message) error {
d.Debug("Launch message received: %+v", msg)
p, err := d.getProfileByIdxOrName(msg.Index, msg.Name)
p, err := d.getProfileFromLaunchMsg(msg)
if err != nil {
return m.Respond(&ErrorMsg{err.Error()})
}
if sbox := d.getRunningSandboxByName(p.Name); sbox != nil {
if msg.Noexec {
errmsg := "Asked to launch program but sandbox is running and noexec is set!"
@ -138,12 +139,12 @@ func (d *daemonState) handleLaunch(msg *LaunchMsg, m *ipc.Message) error {
return m.Respond(&ErrorMsg{errmsg})
} else {
d.Info("Found running sandbox for `%s`, running program there", p.Name)
sbox.launchProgram(msg.Pwd, msg.Args, d.log)
sbox.launchProgram(msg.Path, msg.Pwd, msg.Args, d.log)
}
} else {
d.Debug("Would launch %s", p.Name)
env := d.sanitizeEnvironment(p, msg.Env)
_, err = d.launch(p, msg.Pwd, msg.Args, env, msg.Noexec, m.Ucred.Uid, m.Ucred.Gid, d.log)
msg.Env = d.sanitizeEnvironment(p, msg.Env)
_, err = d.launch(p, msg, m.Ucred.Uid, m.Ucred.Gid, d.log)
if err != nil {
d.Warning("Launch of %s failed: %v", p.Name, err)
return m.Respond(&ErrorMsg{err.Error()})
@ -154,7 +155,7 @@ func (d *daemonState) handleLaunch(msg *LaunchMsg, m *ipc.Message) error {
func (d *daemonState) sanitizeEnvironment(p *oz.Profile, oldEnv []string) ([]string) {
newEnv := []string{}
for _, EnvItem := range d.config.EnvironmentVars {
for _, OldItem := range oldEnv {
if strings.HasPrefix(OldItem, EnvItem+"=") {
@ -183,7 +184,7 @@ func (d *daemonState) sanitizeEnvironment(p *oz.Profile, oldEnv []string) ([]str
}
}
}
return newEnv
}
@ -207,6 +208,28 @@ func (d *daemonState) sandboxById(id int) *Sandbox {
return nil
}
func (d *daemonState) getProfileFromLaunchMsg(msg *LaunchMsg) (*oz.Profile, error) {
if msg.Index == 0 && msg.Name == "" {
return d.getProfileByPath(msg.Path)
}
return d.getProfileByIdxOrName(msg.Index, msg.Name)
}
func (d *daemonState) getProfileByPath(cpath string) (*oz.Profile, error) {
for _, p := range d.profiles {
if p.Path == cpath {
return p, nil
}
for _, pp := range p.Paths {
if pp == cpath {
return p, nil
}
}
}
return nil, fmt.Errorf("could not find profile path '%s'", cpath)
}
func (d *daemonState) getProfileByIdxOrName(index int, name string) (*oz.Profile, error) {
if len(name) == 0 {
if index < 1 || index > len(d.profiles) {
@ -229,7 +252,7 @@ func (d *daemonState) getRunningSandboxByName(name string) *Sandbox {
return sb
}
}
return nil
}

@ -36,7 +36,7 @@ type Sandbox struct {
network *network.SandboxNetwork
}
func createInitCommand(initPath, name, chroot string, env []string, uid uint32, display int, stn *network.SandboxNetwork, nettype string) *exec.Cmd {
func createInitCommand(initPath, name, chroot string, env []string, uid uint32, display int, stn *network.SandboxNetwork) *exec.Cmd {
cmd := exec.Command(initPath)
cmd.Dir = "/"
@ -45,7 +45,7 @@ func createInitCommand(initPath, name, chroot string, env []string, uid uint32,
cloneFlags |= syscall.CLONE_NEWPID
cloneFlags |= syscall.CLONE_NEWUTS
if nettype != "host" {
if stn.Nettype != network.TYPE_HOST {
cloneFlags |= syscall.CLONE_NEWNET
}
@ -74,7 +74,7 @@ func createInitCommand(initPath, name, chroot string, env []string, uid uint32,
return cmd
}
func (d *daemonState) launch(p *oz.Profile, pwd string, args, env []string, noexec bool, uid, gid uint32, log *logging.Logger) (*Sandbox, error) {
func (d *daemonState) launch(p *oz.Profile, msg *LaunchMsg, uid, gid uint32, log *logging.Logger) (*Sandbox, error) {
u, err := user.LookupId(fmt.Sprintf("%d", uid))
if err != nil {
return nil, fmt.Errorf("failed to lookup user for uid=%d: %v", uid, err)
@ -84,20 +84,21 @@ func (d *daemonState) launch(p *oz.Profile, pwd string, args, env []string, noex
return nil, err
}
display := 0
if p.XServer.Enabled && p.Networking.Nettype == "host" {
if p.XServer.Enabled && p.Networking.Nettype == network.TYPE_HOST {
display = d.nextDisplay
d.nextDisplay += 1
}
stn := new(network.SandboxNetwork)
if p.Networking.Nettype == "bridge" {
stn.Nettype = p.Networking.Nettype
if p.Networking.Nettype == network.TYPE_BRIDGE {
stn, err = network.PrepareSandboxNetwork(d.network, log)
if err != nil {
return nil, fmt.Errorf("Unable to prepare veth network: %+v", err)
}
}
cmd := createInitCommand(d.config.InitPath, p.Name, fs.Root(), env, uid, display, stn, p.Networking.Nettype)
cmd := createInitCommand(d.config.InitPath, p.Name, fs.Root(), msg.Env, uid, display, stn)
log.Debug("Command environment: %+v", cmd.Env)
pp, err := cmd.StderrPipe()
if err != nil {
@ -124,18 +125,18 @@ func (d *daemonState) launch(p *oz.Profile, pwd string, args, env []string, noex
network: stn,
}
if p.Networking.Nettype == "bridge" {
if p.Networking.Nettype == network.TYPE_BRIDGE {
if err := network.NetInit(stn, d.network, cmd.Process.Pid, log); err != nil {
cmd.Process.Kill()
fs.Cleanup()
return nil, fmt.Errorf("Unable to create veth networking: %+v", err)
}
}
sbox.ready.Add(1)
go sbox.logMessages()
if p.Networking.Nettype != "host" && len(p.Networking.Sockets) > 0 {
if p.Networking.Nettype != network.TYPE_HOST && len(p.Networking.Sockets) > 0 {
go func() {
sbox.ready.Wait()
err := network.ProxySetup(sbox.init.Process.Pid, p.Networking.Sockets, d.log, sbox.ready)
@ -145,10 +146,10 @@ func (d *daemonState) launch(p *oz.Profile, pwd string, args, env []string, noex
}()
}
if !noexec {
if !msg.Noexec {
go func () {
sbox.ready.Wait()
go sbox.launchProgram(pwd, args, log)
go sbox.launchProgram(msg.Path, msg.Pwd, msg.Args, log)
}()
}
@ -158,13 +159,13 @@ func (d *daemonState) launch(p *oz.Profile, pwd string, args, env []string, noex
go sbox.startXpraClient()
}()
}
d.nextSboxId += 1
d.sandboxes = append(d.sandboxes, sbox)
return sbox, nil
}
func (sbox *Sandbox) launchProgram(pwd string, args []string, log *logging.Logger) {
func (sbox *Sandbox) launchProgram(cpath, pwd string, args []string, log *logging.Logger) {
if sbox.profile.AllowFiles {
for _, fpath := range args {
if _, err := os.Stat(fpath); err == nil {
@ -178,8 +179,8 @@ func (sbox *Sandbox) launchProgram(pwd string, args []string, log *logging.Logge
}
}
}
err := ozinit.RunProgram(sbox.addr, pwd, args)
err := ozinit.RunProgram(sbox.addr, cpath, pwd, args)
if err != nil {
log.Error("start shell command failed: %v", err)
}
@ -190,7 +191,7 @@ func (sbox *Sandbox) remove(log *logging.Logger) {
for _, sb := range sbox.daemon.sandboxes {
if sb == sbox {
sb.fs.Cleanup()
if sb.profile.Networking.Nettype == "bridge" {
if sb.profile.Networking.Nettype == network.TYPE_BRIDGE {
sb.network.Cleanup(log)
}
} else {

@ -32,6 +32,7 @@ type ListProfilesResp struct {
type LaunchMsg struct {
Index int "Launch"
Path string
Name string
Pwd string
Args []string

@ -41,12 +41,12 @@ func Ping(addr string) error {
}
}
func RunProgram(addr, pwd string, args []string) error {
func RunProgram(addr, cpath, pwd string, args []string) error {
c, err := clientConnect(addr)
if err != nil {
return err
}
rr, err := c.ExchangeMsg(&RunProgramMsg{Args: args, Pwd: pwd})
rr, err := c.ExchangeMsg(&RunProgramMsg{Path: cpath, Args: args, Pwd: pwd})
resp := <-rr.Chan()
rr.Done()
c.Close()

@ -4,7 +4,6 @@ import (
"bufio"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"os/exec"
@ -69,8 +68,9 @@ func parseArgs() *initState {
log.Error("oz-init must run as root\n")
os.Exit(1)
}
pcontents, _ := ioutil.ReadFile("/proc/1/cmdline")
if len(pcontents) > 0 {
// We should check that the file contains config.InitPath, but
// since proc is not mounted in this state is still doesn't exist.
if _, err := os.Stat("/proc/1/cmdline"); !os.IsNotExist(err) {
log.Error("What are you doing? Oz-init cannot be launched manually")
os.Exit(1)
}
@ -156,13 +156,13 @@ func parseArgs() *initState {
env = append(env, e)
}
}
env = append(env, "PATH=/usr/bin:/bin")
if p.XServer.Enabled {
env = append(env, "DISPLAY=:"+strconv.Itoa(display))
}
return &initState{
log: log,
config: config,
@ -186,8 +186,8 @@ func (st *initState) runInit() {
if homedir, _ := st.fs.GetHomeDir(); homedir != "" {
st.launchEnv = append(st.launchEnv, "HOME="+homedir)
}
if st.profile.Networking.Nettype != "host" {
if st.profile.Networking.Nettype != network.TYPE_HOST {
err := network.NetSetup(st.network)
if err != nil {
st.log.Error("Unable to setup networking: %+v", err)
@ -289,12 +289,15 @@ func (st *initState) readXpraOutput(r io.ReadCloser) {
}
}
func (st *initState) launchApplication(pwd string, cmdArgs []string) (*exec.Cmd, error) {
func (st *initState) launchApplication(cpath, pwd string, cmdArgs []string) (*exec.Cmd, error) {
suffix := ""
if st.config.DivertSuffix != "" {
suffix = "."+st.config.DivertSuffix
}
cmd := exec.Command(st.profile.Path+suffix)
if cpath == "" {
cpath = st.profile.Path
}
cmd := exec.Command(cpath+suffix)
stdout, err := cmd.StdoutPipe()
if err != nil {
st.log.Warning("Failed to create stdout pipe: %v", err)
@ -311,13 +314,13 @@ func (st *initState) launchApplication(pwd string, cmdArgs []string) (*exec.Cmd,
Gid: uint32(st.gid),
}
cmd.Env = append(cmd.Env, st.launchEnv...)
cmd.Args = append(cmd.Args, cmdArgs...)
if _, err := os.Stat(pwd); err == nil {
cmd.Dir = pwd
}
if err := cmd.Start(); err != nil {
st.log.Warning("Failed to start application (%s): %v", st.profile.Path, err)
return nil, err
@ -326,7 +329,7 @@ func (st *initState) launchApplication(pwd string, cmdArgs []string) (*exec.Cmd,
go st.readApplicationOutput(stdout, "stdout")
go st.readApplicationOutput(stderr, "stderr")
return cmd, nil
}
@ -357,7 +360,7 @@ func handlePing(ping *PingMsg, msg *ipc.Message) error {
func (st *initState) handleRunProgram(rp *RunProgramMsg, msg *ipc.Message) error {
st.log.Info("Run program message received: %+v", rp)
_, err := st.launchApplication(rp.Pwd, rp.Args)
_, err := st.launchApplication(rp.Path, rp.Pwd, rp.Args)
if err != nil {
err := msg.Respond(&ErrorMsg{Msg: err.Error()})
return err

@ -21,6 +21,7 @@ type RunShellMsg struct {
type RunProgramMsg struct {
Args []string "RunProgram"
Pwd string
Path string
}
var messageFactory = ipc.NewMsgFactory(

@ -5,6 +5,7 @@ import (
"io"
"os"
"path"
"path/filepath"
"strconv"
"github.com/subgraph/oz"
@ -41,7 +42,14 @@ func runSandbox() {
os.Exit(1)
}
err := daemon.Launch(runBasename, os.Args[1:], os.Environ(), false)
name := "0"
cpath := os.Args[0]
if !filepath.IsAbs(os.Args[0]) {
// TODO: Check for executable in path...
name = cpath
cpath = ""
}
err := daemon.Launch(name, cpath, os.Args[1:], os.Environ(), false)
if err != nil {
fmt.Fprintf(os.Stderr, "launch command failed: %v.\n", err)
os.Exit(1)
@ -121,7 +129,7 @@ func handleLaunch(c *cli.Context) {
fmt.Println("Argument needed to launch command")
os.Exit(1)
}
err := daemon.Launch(c.Args()[0], c.Args()[1:], os.Environ(), noexec)
err := daemon.Launch(c.Args()[0], "", c.Args()[1:], os.Environ(), noexec)
if err != nil {
fmt.Printf("launch command failed: %v\n", err)
os.Exit(1)

@ -5,7 +5,7 @@ import (
"fmt"
"io/ioutil"
"path"
"github.com/subgraph/oz/network"
)
@ -14,6 +14,8 @@ type Profile struct {
Name string
// Path to binary to launch
Path string
// List of path to binaries matching this sandbox
Paths []string
// Path of the config file
ProfilePath string `json:"-"`
// Optional path of binary to watch for watchdog purposes if different than Path
@ -70,7 +72,7 @@ type EnvVar struct {
// Sandbox network definition
type NetworkProfile struct {
// One of empty, host, bridge
Nettype string `json:"type"`
Nettype network.NetType `json:"type"`
// Name of the bridge to attach to
//Bridge string
@ -86,6 +88,20 @@ var loadedProfiles []*Profile
type Profiles []*Profile
func NewDefaultProfile() *Profile {
return &Profile{
Multi: false,
AllowFiles: false,
XServer: XServerConf{
Enabled: true,
EnableTray: false,
UseDBUS: false,
UsePulseAudio: false,
DisableAudio: true,
},
}
}
func (ps Profiles) GetProfileByName(name string) (*Profile, error) {
if loadedProfiles == nil {
ps, err := LoadProfiles(defaultProfileDirectory)
@ -116,6 +132,11 @@ func (ps Profiles) GetProfileByPath(bpath string) (*Profile, error) {
if p.Path == bpath {
return p, nil
}
for _, pp := range p.Paths {
if pp == bpath {
return p, nil
}
}
}
return nil, nil
}
@ -136,7 +157,7 @@ func LoadProfiles(dir string) (Profiles, error) {
ps = append(ps, p)
}
}
loadedProfiles = ps
return ps, nil
}

@ -1,5 +1,10 @@
{
"path": "/usr/bin/gajim"
"name": "gajim"
, "path": "/usr/bin/gajim"
, "paths": [
"/usr/bin/gajim-history-manager"
, "/usr/bin/gajim-remote"
]
, "xserver": {
"enabled": true
, "enable_tray": true

@ -0,0 +1,31 @@
{
"name": "libreoffice"
, "path": "/usr/bin/libreoffice"
, "paths": [
"/usr/bin/lowriter"
, "/usr/bin/lobase"
, "/usr/bin/localc"
, "/usr/share/libreoffice/bin/lo-xlate-lang"
, "/usr/bin/loffice"
, "/usr/bin/unopkg"
, "/usr/bin/lofromtemplate"
, "/usr/bin/soffice"
, "/usr/bin/lodraw"
, "/usr/bin/loimpress"
, "/usr/bin/lomath"
, "/usr/bin/loweb"
, "/usr/bin/lowriter"
]
, "allow_files": true
, "xserver": {
"enabled": true
, "enable_tray": true
, "tray_icon":"/usr/share/icons/gnome/scalable/apps/libreoffice-startcenter.svg"
, "window_icon":"/usr/share/icons/gnome/scalable/apps/libreoffice-startcenter.svg"
, "disable_audio": true
, "use_pulse_audio": false
}
, "networking":{
"type":"empty"
}
}
Loading…
Cancel
Save