app: support mapping target uid as privileged uid in sandbox
test / test (push) Successful in 40s
Details
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:
parent
7962681f4a
commit
af15b1c048
|
@ -8,11 +8,6 @@ import (
|
||||||
"git.ophivana.moe/security/fortify/internal/system"
|
"git.ophivana.moe/security/fortify/internal/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
mappedID = 65534
|
|
||||||
mappedIDString = "65534"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config is used to seal an *App
|
// Config is used to seal an *App
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// D-Bus application ID
|
// D-Bus application ID
|
||||||
|
@ -54,6 +49,8 @@ type SandboxConfig struct {
|
||||||
Net bool `json:"net,omitempty"`
|
Net bool `json:"net,omitempty"`
|
||||||
// do not run in new session
|
// do not run in new session
|
||||||
NoNewSession bool `json:"no_new_session,omitempty"`
|
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
|
// mediated access to wayland socket
|
||||||
Wayland bool `json:"wayland,omitempty"`
|
Wayland bool `json:"wayland,omitempty"`
|
||||||
|
|
||||||
|
@ -82,11 +79,15 @@ type FilesystemConfig struct {
|
||||||
|
|
||||||
// Bwrap returns the address of the corresponding bwrap.Config to s.
|
// 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.
|
// 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 {
|
if s == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !s.UseRealUID {
|
||||||
|
uid = 65534
|
||||||
|
}
|
||||||
|
|
||||||
conf := (&bwrap.Config{
|
conf := (&bwrap.Config{
|
||||||
Net: s.Net,
|
Net: s.Net,
|
||||||
UserNS: s.UserNS,
|
UserNS: s.UserNS,
|
||||||
|
@ -100,7 +101,7 @@ func (s *SandboxConfig) Bwrap() *bwrap.Config {
|
||||||
// initialise map
|
// initialise map
|
||||||
Chmod: make(map[string]os.FileMode),
|
Chmod: make(map[string]os.FileMode),
|
||||||
}).
|
}).
|
||||||
SetUID(mappedID).SetGID(mappedID).
|
SetUID(uid).SetGID(uid).
|
||||||
Procfs("/proc").DevTmpfs("/dev").Mqueue("/dev/mqueue").
|
Procfs("/proc").DevTmpfs("/dev").Mqueue("/dev/mqueue").
|
||||||
Tmpfs("/dev/fortify", 4*1024)
|
Tmpfs("/dev/fortify", 4*1024)
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,15 @@ func (a *app) Seal(config *Config) error {
|
||||||
// create seal system component
|
// create seal system component
|
||||||
seal.sys = new(appSealSys)
|
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
|
// look up user from system
|
||||||
if u, err := a.os.Lookup(config.User); err != nil {
|
if u, err := a.os.Lookup(config.User); err != nil {
|
||||||
if errors.As(err, new(user.UnknownUserError)) {
|
if errors.As(err, new(user.UnknownUserError)) {
|
||||||
|
@ -139,7 +148,6 @@ func (a *app) Seal(config *Config) error {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
seal.sys.user = u
|
seal.sys.user = u
|
||||||
seal.sys.runtime = path.Join("/run/user", mappedIDString)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// map sandbox config to bwrap
|
// map sandbox config to bwrap
|
||||||
|
@ -228,7 +236,7 @@ func (a *app) Seal(config *Config) error {
|
||||||
|
|
||||||
config.Confinement.Sandbox = conf
|
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
|
seal.sys.override = config.Confinement.Sandbox.Override
|
||||||
if seal.sys.bwrap.SetEnv == nil {
|
if seal.sys.bwrap.SetEnv == nil {
|
||||||
seal.sys.bwrap.SetEnv = make(map[string]string)
|
seal.sys.bwrap.SetEnv = make(map[string]string)
|
||||||
|
|
|
@ -58,12 +58,12 @@ func (seal *appSeal) sharePasswd(os linux.System) {
|
||||||
homeDir = seal.sys.user.HomeDir
|
homeDir = seal.sys.user.HomeDir
|
||||||
seal.sys.bwrap.SetEnv["HOME"] = 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)
|
seal.sys.Write(passwdPath, passwd)
|
||||||
|
|
||||||
// write /etc/group
|
// write /etc/group
|
||||||
groupPath := path.Join(seal.share, "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
|
// bind /etc/passwd and /etc/group
|
||||||
seal.sys.bwrap.Bind(passwdPath, "/etc/passwd")
|
seal.sys.bwrap.Bind(passwdPath, "/etc/passwd")
|
||||||
|
|
|
@ -20,6 +20,11 @@ type appSealSys struct {
|
||||||
// target user sealed from config
|
// target user sealed from config
|
||||||
user *user.User
|
user *user.User
|
||||||
|
|
||||||
|
// mapped uid and gid in user namespace
|
||||||
|
mappedID int
|
||||||
|
// string representation of mappedID
|
||||||
|
mappedIDString string
|
||||||
|
|
||||||
needRevert bool
|
needRevert bool
|
||||||
saveState bool
|
saveState bool
|
||||||
*system.I
|
*system.I
|
||||||
|
|
Loading…
Reference in New Issue