app: support mapping target uid as privileged uid in sandbox
test / test (push) Successful in 40s Details

Chromium's D-Bus client implementation refuses to work when its getuid call returns a different value than what the D-Bus server is running as. The reason behind this is not fully understood, but this workaround is implemented to support chromium and electron apps. This is not used by default since it has many side effects that break many other programs, like SSH on NixOS.

Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
This commit is contained in:
Ophestra Umiker 2024-11-04 03:15:39 +09:00
parent 7962681f4a
commit af15b1c048
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
4 changed files with 25 additions and 11 deletions

View File

@ -8,11 +8,6 @@ import (
"git.ophivana.moe/security/fortify/internal/system"
)
const (
mappedID = 65534
mappedIDString = "65534"
)
// Config is used to seal an *App
type Config struct {
// D-Bus application ID
@ -54,6 +49,8 @@ type SandboxConfig struct {
Net bool `json:"net,omitempty"`
// do not run in new session
NoNewSession bool `json:"no_new_session,omitempty"`
// map target user uid to privileged user uid in the user namespace
UseRealUID bool `json:"use_real_uid"`
// mediated access to wayland socket
Wayland bool `json:"wayland,omitempty"`
@ -82,11 +79,15 @@ type FilesystemConfig struct {
// Bwrap returns the address of the corresponding bwrap.Config to s.
// Note that remaining tmpfs entries must be queued by the caller prior to launch.
func (s *SandboxConfig) Bwrap() *bwrap.Config {
func (s *SandboxConfig) Bwrap(uid int) *bwrap.Config {
if s == nil {
return nil
}
if !s.UseRealUID {
uid = 65534
}
conf := (&bwrap.Config{
Net: s.Net,
UserNS: s.UserNS,
@ -100,7 +101,7 @@ func (s *SandboxConfig) Bwrap() *bwrap.Config {
// initialise map
Chmod: make(map[string]os.FileMode),
}).
SetUID(mappedID).SetGID(mappedID).
SetUID(uid).SetGID(uid).
Procfs("/proc").DevTmpfs("/dev").Mqueue("/dev/mqueue").
Tmpfs("/dev/fortify", 4*1024)

View File

@ -129,6 +129,15 @@ func (a *app) Seal(config *Config) error {
// create seal system component
seal.sys = new(appSealSys)
// mapped uid
if config.Confinement.Sandbox != nil && config.Confinement.Sandbox.UseRealUID {
seal.sys.mappedID = a.os.Geteuid()
} else {
seal.sys.mappedID = 65534
}
seal.sys.mappedIDString = strconv.Itoa(seal.sys.mappedID)
seal.sys.runtime = path.Join("/run/user", seal.sys.mappedIDString)
// look up user from system
if u, err := a.os.Lookup(config.User); err != nil {
if errors.As(err, new(user.UnknownUserError)) {
@ -139,7 +148,6 @@ func (a *app) Seal(config *Config) error {
}
} else {
seal.sys.user = u
seal.sys.runtime = path.Join("/run/user", mappedIDString)
}
// map sandbox config to bwrap
@ -228,7 +236,7 @@ func (a *app) Seal(config *Config) error {
config.Confinement.Sandbox = conf
}
seal.sys.bwrap = config.Confinement.Sandbox.Bwrap()
seal.sys.bwrap = config.Confinement.Sandbox.Bwrap(a.os.Geteuid())
seal.sys.override = config.Confinement.Sandbox.Override
if seal.sys.bwrap.SetEnv == nil {
seal.sys.bwrap.SetEnv = make(map[string]string)

View File

@ -58,12 +58,12 @@ func (seal *appSeal) sharePasswd(os linux.System) {
homeDir = seal.sys.user.HomeDir
seal.sys.bwrap.SetEnv["HOME"] = seal.sys.user.HomeDir
}
passwd := username + ":x:" + mappedIDString + ":" + mappedIDString + ":Fortify:" + homeDir + ":" + sh + "\n"
passwd := username + ":x:" + seal.sys.mappedIDString + ":" + seal.sys.mappedIDString + ":Fortify:" + homeDir + ":" + sh + "\n"
seal.sys.Write(passwdPath, passwd)
// write /etc/group
groupPath := path.Join(seal.share, "group")
seal.sys.Write(groupPath, "fortify:x:"+mappedIDString+":\n")
seal.sys.Write(groupPath, "fortify:x:"+seal.sys.mappedIDString+":\n")
// bind /etc/passwd and /etc/group
seal.sys.bwrap.Bind(passwdPath, "/etc/passwd")

View File

@ -20,6 +20,11 @@ type appSealSys struct {
// target user sealed from config
user *user.User
// mapped uid and gid in user namespace
mappedID int
// string representation of mappedID
mappedIDString string
needRevert bool
saveState bool
*system.I