All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 32s
				
			Test / Sandbox (push) Successful in 2m19s
				
			Test / Hakurei (push) Successful in 3m9s
				
			Test / Hpkg (push) Successful in 3m53s
				
			Test / Sandbox (race detector) (push) Successful in 4m2s
				
			Test / Hakurei (race detector) (push) Successful in 4m43s
				
			Test / Flake checks (push) Successful in 1m23s
				
			This package will also hold syscall lookup tables for seccomp. Signed-off-by: Ophestra <cat@gensokyo.uk>
		
			
				
	
	
		
			189 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package dbus
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"errors"
 | 
						|
	"os"
 | 
						|
	"os/exec"
 | 
						|
	"strconv"
 | 
						|
	"syscall"
 | 
						|
 | 
						|
	"hakurei.app/container"
 | 
						|
	"hakurei.app/container/check"
 | 
						|
	"hakurei.app/container/comp"
 | 
						|
	"hakurei.app/container/seccomp"
 | 
						|
	"hakurei.app/helper"
 | 
						|
	"hakurei.app/ldd"
 | 
						|
)
 | 
						|
 | 
						|
// Start starts and configures a D-Bus proxy process.
 | 
						|
func (p *Proxy) Start() error {
 | 
						|
	if p.final == nil || p.final.WriterTo == nil {
 | 
						|
		return syscall.ENOTRECOVERABLE
 | 
						|
	}
 | 
						|
 | 
						|
	p.mu.Lock()
 | 
						|
	defer p.mu.Unlock()
 | 
						|
	p.pmu.Lock()
 | 
						|
	defer p.pmu.Unlock()
 | 
						|
 | 
						|
	if p.cancel != nil || p.cause != nil {
 | 
						|
		return errors.New("dbus: already started")
 | 
						|
	}
 | 
						|
 | 
						|
	ctx, cancel := context.WithCancelCause(p.ctx)
 | 
						|
 | 
						|
	if !p.useSandbox {
 | 
						|
		p.helper = helper.NewDirect(ctx, p.name, p.final, true, argF, func(cmd *exec.Cmd) {
 | 
						|
			if p.output != nil {
 | 
						|
				cmd.Stdout, cmd.Stderr = p.output, p.output
 | 
						|
			}
 | 
						|
			cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
 | 
						|
			cmd.Env = make([]string, 0)
 | 
						|
		}, nil)
 | 
						|
	} else {
 | 
						|
		var toolPath *check.Absolute
 | 
						|
		if a, err := check.NewAbs(p.name); err != nil {
 | 
						|
			if p.name, err = exec.LookPath(p.name); err != nil {
 | 
						|
				return err
 | 
						|
			} else if toolPath, err = check.NewAbs(p.name); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			toolPath = a
 | 
						|
		}
 | 
						|
 | 
						|
		var libPaths []*check.Absolute
 | 
						|
		if entries, err := ldd.Exec(ctx, p.msg, toolPath.String()); err != nil {
 | 
						|
			return err
 | 
						|
		} else {
 | 
						|
			libPaths = ldd.Path(entries)
 | 
						|
		}
 | 
						|
 | 
						|
		p.helper = helper.New(
 | 
						|
			ctx, p.msg, toolPath, "xdg-dbus-proxy",
 | 
						|
			p.final, true,
 | 
						|
			argF, func(z *container.Container) {
 | 
						|
				z.SeccompFlags |= seccomp.AllowMultiarch
 | 
						|
				z.SeccompPresets |= comp.PresetStrict
 | 
						|
				z.Hostname = "hakurei-dbus"
 | 
						|
				if p.output != nil {
 | 
						|
					z.Stdout, z.Stderr = p.output, p.output
 | 
						|
				}
 | 
						|
 | 
						|
				// these lib paths are unpredictable, so mount them first so they cannot cover anything
 | 
						|
				for _, name := range libPaths {
 | 
						|
					z.Bind(name, name, 0)
 | 
						|
				}
 | 
						|
 | 
						|
				// upstream bus directories
 | 
						|
				upstreamPaths := make([]*check.Absolute, 0, 2)
 | 
						|
				for _, addr := range [][]AddrEntry{p.final.SessionUpstream, p.final.SystemUpstream} {
 | 
						|
					for _, ent := range addr {
 | 
						|
						if ent.Method != "unix" {
 | 
						|
							continue
 | 
						|
						}
 | 
						|
						for _, pair := range ent.Values {
 | 
						|
							if pair[0] != "path" {
 | 
						|
								continue
 | 
						|
							}
 | 
						|
							if a, err := check.NewAbs(pair[1]); err != nil {
 | 
						|
								continue
 | 
						|
							} else {
 | 
						|
								upstreamPaths = append(upstreamPaths, a.Dir())
 | 
						|
							}
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
				check.SortAbs(upstreamPaths)
 | 
						|
				upstreamPaths = check.CompactAbs(upstreamPaths)
 | 
						|
				for _, name := range upstreamPaths {
 | 
						|
					z.Bind(name, name, 0)
 | 
						|
				}
 | 
						|
				z.HostNet = len(upstreamPaths) == 0
 | 
						|
				z.HostAbstract = z.HostNet
 | 
						|
 | 
						|
				// parent directories of bind paths
 | 
						|
				sockDirPaths := make([]*check.Absolute, 0, 2)
 | 
						|
				if a, err := check.NewAbs(p.final.Session[1]); err == nil {
 | 
						|
					sockDirPaths = append(sockDirPaths, a.Dir())
 | 
						|
				}
 | 
						|
				if a, err := check.NewAbs(p.final.System[1]); err == nil {
 | 
						|
					sockDirPaths = append(sockDirPaths, a.Dir())
 | 
						|
				}
 | 
						|
				check.SortAbs(sockDirPaths)
 | 
						|
				sockDirPaths = check.CompactAbs(sockDirPaths)
 | 
						|
				for _, name := range sockDirPaths {
 | 
						|
					z.Bind(name, name, comp.BindWritable)
 | 
						|
				}
 | 
						|
 | 
						|
				// xdg-dbus-proxy bin path
 | 
						|
				binPath := toolPath.Dir()
 | 
						|
				z.Bind(binPath, binPath, 0)
 | 
						|
			}, nil)
 | 
						|
	}
 | 
						|
 | 
						|
	if err := p.helper.Start(); err != nil {
 | 
						|
		cancel(err)
 | 
						|
		p.helper = nil
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	p.cancel, p.cause = cancel, func() error { return context.Cause(ctx) }
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
var proxyClosed = errors.New("proxy closed")
 | 
						|
 | 
						|
// Wait blocks until xdg-dbus-proxy exits and releases resources.
 | 
						|
func (p *Proxy) Wait() error {
 | 
						|
	p.mu.RLock()
 | 
						|
	defer p.mu.RUnlock()
 | 
						|
 | 
						|
	p.pmu.RLock()
 | 
						|
	if p.helper == nil || p.cancel == nil || p.cause == nil {
 | 
						|
		p.pmu.RUnlock()
 | 
						|
		return errors.New("dbus: not started")
 | 
						|
	}
 | 
						|
 | 
						|
	var errs [3]error
 | 
						|
 | 
						|
	errs[0] = p.helper.Wait()
 | 
						|
	if errors.Is(errs[0], context.Canceled) &&
 | 
						|
		errors.Is(p.cause(), proxyClosed) {
 | 
						|
		errs[0] = nil
 | 
						|
	}
 | 
						|
	p.pmu.RUnlock()
 | 
						|
 | 
						|
	// ensure socket removal so ephemeral directory is empty at revert
 | 
						|
	if err := os.Remove(p.final.Session[1]); err != nil && !errors.Is(err, os.ErrNotExist) {
 | 
						|
		errs[1] = err
 | 
						|
	}
 | 
						|
	if p.final.System[1] != "" {
 | 
						|
		if err := os.Remove(p.final.System[1]); err != nil && !errors.Is(err, os.ErrNotExist) {
 | 
						|
			errs[2] = err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return errors.Join(errs[:]...)
 | 
						|
}
 | 
						|
 | 
						|
// Close cancels the context passed to the helper instance attached to xdg-dbus-proxy.
 | 
						|
func (p *Proxy) Close() {
 | 
						|
	p.pmu.Lock()
 | 
						|
	defer p.pmu.Unlock()
 | 
						|
 | 
						|
	if p.cancel == nil {
 | 
						|
		panic("dbus: not started")
 | 
						|
	}
 | 
						|
	p.cancel(proxyClosed)
 | 
						|
}
 | 
						|
 | 
						|
func argF(argsFd, statFd int) []string {
 | 
						|
	if statFd == -1 {
 | 
						|
		return []string{"--args=" + strconv.Itoa(argsFd)}
 | 
						|
	} else {
 | 
						|
		return []string{"--args=" + strconv.Itoa(argsFd), "--fd=" + strconv.Itoa(statFd)}
 | 
						|
	}
 | 
						|
}
 |