diff --git a/oz-init/init.go b/oz-init/init.go index 1291fd3..a5761b7 100644 --- a/oz-init/init.go +++ b/oz-init/init.go @@ -2,6 +2,7 @@ package ozinit import ( "bufio" + "bytes" "encoding/json" "fmt" "io" @@ -11,6 +12,7 @@ import ( "os/signal" "os/user" "path" + "regexp" "strconv" "strings" "sync" @@ -44,6 +46,7 @@ type initState struct { xpra *xpra.Xpra xpraReady sync.WaitGroup network *network.SandboxNetwork + dbusUuid string } type InitData struct { @@ -59,6 +62,12 @@ type InitData struct { Display int } +const ( + DBUS_VAR_REGEXP = "[A-Za-z_]+=[a-zA-Z_:-@]+=/tmp/.+" +) + +var dbusValidVar = regexp.MustCompile(DBUS_VAR_REGEXP) + // By convention oz-init writes log messages to stderr with a single character // prefix indicating the logging level. These messages are read one line at a time // over a pipe by oz-daemon and translated into appropriate log events. @@ -164,12 +173,20 @@ func (st *initState) runInit() { if syscall.Sethostname([]byte(st.profile.Name)) != nil { st.log.Error("Failed to set hostname to (%s)", st.profile.Name) + os.Exit(1) } if syscall.Setdomainname([]byte("local")) != nil { st.log.Error("Failed to set domainname") } st.log.Info("Hostname set to (%s.local)", st.profile.Name) + if st.needsDbus() { + if err := st.setupDbus(); err != nil { + st.log.Error("Unable to setup dbus: %v", err) + os.Exit(1) + } + } + oz.ReapChildProcs(st.log, st.handleChildExit) if st.profile.XServer.Enabled { @@ -179,6 +196,13 @@ func (st *initState) runInit() { st.xpraReady.Wait() st.log.Info("XPRA started") + if st.needsDbus() { + if err := st.getDbusSession(); err != nil { + st.log.Error("Unable to get dbus session information: %v", err) + os.Exit(1) + } + } + fsbx := path.Join("/tmp", "oz-sandbox") err = ioutil.WriteFile(fsbx, []byte(st.profile.Name), 0644) @@ -195,6 +219,63 @@ func (st *initState) runInit() { st.log.Info("oz-init exiting...") } +func (st *initState) needsDbus() bool { + return (st.profile.XServer.AudioMode == oz.PROFILE_AUDIO_FULL || + st.profile.XServer.AudioMode == oz.PROFILE_AUDIO_SPEAKER || + st.profile.XServer.EnableNotifications == true) +} + +func (st *initState) setupDbus() error { + exec.Command("/usr/bin/dbus-uuidgen", "--ensure").Run() + buuid, err := exec.Command("/usr/bin/dbus-uuidgen", "--get").CombinedOutput() + if err != nil || string(buuid) == "" { + return fmt.Errorf("dbus-uuidgen failed: %v %v", err, string(buuid)) + } + st.dbusUuid = strings.TrimSpace(string(bytes.Trim(buuid, "\x00"))) + st.log.Debug("dbus-uuid: %s", st.dbusUuid) + return nil +} + +func (st *initState) getDbusSession() error { + args := []string{ + "--autolaunch", + st.dbusUuid, + "--sh-syntax", + "--close-stderr", + } + dcmd := exec.Command("/usr/bin/dbus-launch", args...) + dcmd.Env = append([]string{}, st.launchEnv...) + st.log.Debug("%s /usr/bin/dbus-launch %s", strings.Join(dcmd.Env, " "), strings.Join(args, " ")) + dcmd.SysProcAttr = &syscall.SysProcAttr{} + dcmd.SysProcAttr.Credential = &syscall.Credential{ + Uid: st.uid, + Gid: st.gid, + } + + benvs, err := dcmd.Output() + if err != nil && len(benvs) <= 1 { + return fmt.Errorf("dbus-launch failed: %v %v", err, string(benvs)) + } + benvs = bytes.Trim(benvs, "\x00") + senvs := strings.TrimSpace(string(benvs)) + senvs = strings.Replace(senvs, "export ", "", -1) + senvs = strings.Replace(senvs, ";", "", -1) + senvs = strings.Replace(senvs, "'", "", -1) + dbusenv := "" + for _, line := range strings.Split(senvs, "\n") { + if dbusValidVar.MatchString(line) { + dbusenv = line + break; + } + } + if dbusenv != "" { + st.launchEnv = append(st.launchEnv, dbusenv) + vv := strings.Split(dbusenv, "=") + os.Setenv(vv[0], strings.Join(vv[1:], "=")) + } + return nil +} + func (st *initState) startXpraServer() { if st.user == nil { st.log.Warning("Cannot start xpra server because no user is set") diff --git a/oz-init/rootfs.go b/oz-init/rootfs.go index 38ff686..3d4fc2d 100644 --- a/oz-init/rootfs.go +++ b/oz-init/rootfs.go @@ -7,7 +7,7 @@ import ( "path" "strconv" "syscall" - + "github.com/subgraph/oz/fs" ) @@ -18,7 +18,7 @@ var basicBindDirs = []string{ var basicEmptyDirs = []string{ "/boot", "/dev", "/home", "/media", "/mnt", "/opt", "/proc", "/root", "/run", "/run/lock", "/run/user", - "/sbin", "/srv", "/sys", "/tmp", "/var", "/var/lib", + "/sbin", "/srv", "/sys", "/tmp", "/var", "/var/lib", "/var/lib/dbus", "/var/cache", "/var/crash", } @@ -38,7 +38,12 @@ var deviceSymlinks = [][2]string{ } var basicBlacklist = []string{ - "/usr/sbin", "/sbin", "/etc/X11", + /*"${PATH}/dbus-daemon", "${PATH}/dbus-launch", "${PATH}/pulseaudio",*/ + "/usr/lib/gvfs", + + "/usr/sbin", "/sbin", + + "/etc/X11", "/etc/machine-id", "${PATH}/sudo", "${PATH}/su", "${PATH}/xinput", "${PATH}/strace", "${PATH}/mount", "${PATH}/umount",