app: merge seal with sys
The existence of the appSealSys struct was an implementation detail obsolete since system.I was integrated in 084cd84f36
.
Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
53571f030e
commit
dfd9467523
@ -47,10 +47,10 @@ func (a *app) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if a.appSeal != nil {
|
if a.appSeal != nil {
|
||||||
if a.appSeal.sys.user.uid == nil {
|
if a.appSeal.user.uid == nil {
|
||||||
return fmt.Sprintf("(sealed app %s with invalid uid)", a.id)
|
return fmt.Sprintf("(sealed app %s with invalid uid)", a.id)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("(sealed app %s as uid %s)", a.id, a.appSeal.sys.user.uid)
|
return fmt.Sprintf("(sealed app %s as uid %s)", a.id, a.appSeal.user.uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("(unsealed app %s)", a.id)
|
return fmt.Sprintf("(unsealed app %s)", a.id)
|
||||||
|
@ -16,5 +16,5 @@ func NewWithID(id fst.ID, os sys.State) fst.App {
|
|||||||
|
|
||||||
func AppSystemBwrap(a fst.App) (*system.I, *bwrap.Config) {
|
func AppSystemBwrap(a fst.App) (*system.I, *bwrap.Config) {
|
||||||
v := a.(*app)
|
v := a.(*app)
|
||||||
return v.appSeal.sys.I, v.appSeal.sys.bwrap
|
return v.appSeal.sys, v.appSeal.container
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
@ -42,8 +43,13 @@ type appSeal struct {
|
|||||||
appID string
|
appID string
|
||||||
// final argv, passed to init
|
// final argv, passed to init
|
||||||
command []string
|
command []string
|
||||||
// state instance initialised during seal and used on process lifecycle events
|
|
||||||
|
// state instance initialised during seal; used during process lifecycle events
|
||||||
store state.Store
|
store state.Store
|
||||||
|
// whether [system.I] was committed; used during process lifecycle events
|
||||||
|
needRevert bool
|
||||||
|
// whether state was inserted into [state.Store]; used during process lifecycle events
|
||||||
|
stateInStore bool
|
||||||
|
|
||||||
// process-specific share directory path ([os.TempDir])
|
// process-specific share directory path ([os.TempDir])
|
||||||
share string
|
share string
|
||||||
@ -57,13 +63,24 @@ type appSeal struct {
|
|||||||
// when this gets set no attempt is made to attach security-context-v1
|
// when this gets set no attempt is made to attach security-context-v1
|
||||||
// and the bare socket is mounted to the sandbox
|
// and the bare socket is mounted to the sandbox
|
||||||
directWayland bool
|
directWayland bool
|
||||||
|
// mount tmpfs over these paths, runs right before extraPerms
|
||||||
|
override []string
|
||||||
// extra [acl.Update] ops, appended at the end of [system.I]
|
// extra [acl.Update] ops, appended at the end of [system.I]
|
||||||
extraPerms []*sealedExtraPerm
|
extraPerms []*sealedExtraPerm
|
||||||
|
|
||||||
|
// post fsu state
|
||||||
|
user appUser
|
||||||
|
// inner XDG_RUNTIME_DIR, default formatting via user
|
||||||
|
innerRuntimeDir string
|
||||||
|
// mapped uid and gid in user namespace
|
||||||
|
mapuid *stringPair[int]
|
||||||
|
|
||||||
|
sys *system.I
|
||||||
|
container *bwrap.Config
|
||||||
|
bwrapSync *os.File
|
||||||
|
|
||||||
// prevents sharing from happening twice
|
// prevents sharing from happening twice
|
||||||
shared bool
|
shared bool
|
||||||
// seal system-level component
|
|
||||||
sys *appSealSys
|
|
||||||
|
|
||||||
system.Enablements
|
system.Enablements
|
||||||
fst.Paths
|
fst.Paths
|
||||||
@ -71,6 +88,24 @@ type appSeal struct {
|
|||||||
// protected by upstream mutex
|
// protected by upstream mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// appUser stores post-fsu credentials and metadata
|
||||||
|
type appUser struct {
|
||||||
|
// application id
|
||||||
|
aid *stringPair[int]
|
||||||
|
// target uid resolved by fid:aid
|
||||||
|
uid *stringPair[int]
|
||||||
|
|
||||||
|
// supplementary group ids
|
||||||
|
supp []string
|
||||||
|
|
||||||
|
// home directory host path
|
||||||
|
data string
|
||||||
|
// app user home directory
|
||||||
|
home string
|
||||||
|
// passwd database username
|
||||||
|
username string
|
||||||
|
}
|
||||||
|
|
||||||
type sealedExtraPerm struct {
|
type sealedExtraPerm struct {
|
||||||
name string
|
name string
|
||||||
perms acl.Perms
|
perms acl.Perms
|
||||||
@ -110,9 +145,6 @@ func (a *app) Seal(config *fst.Config) error {
|
|||||||
seal.appID = config.ID
|
seal.appID = config.ID
|
||||||
seal.command = config.Command
|
seal.command = config.Command
|
||||||
|
|
||||||
// create seal system component
|
|
||||||
seal.sys = new(appSealSys)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// mapped uid defaults to 65534 to work around file ownership checks due to a bwrap limitation
|
// mapped uid defaults to 65534 to work around file ownership checks due to a bwrap limitation
|
||||||
mapuid := 65534
|
mapuid := 65534
|
||||||
@ -121,8 +153,8 @@ func (a *app) Seal(config *fst.Config) error {
|
|||||||
// separate workaround is introduced to map priv-side caller uid in namespace
|
// separate workaround is introduced to map priv-side caller uid in namespace
|
||||||
mapuid = a.sys.Geteuid()
|
mapuid = a.sys.Geteuid()
|
||||||
}
|
}
|
||||||
seal.sys.mapuid = newInt(mapuid)
|
seal.mapuid = newInt(mapuid)
|
||||||
seal.sys.runtime = path.Join("/run/user", seal.sys.mapuid.String())
|
seal.innerRuntimeDir = path.Join("/run/user", seal.mapuid.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate uid and set user info
|
// validate uid and set user info
|
||||||
@ -130,42 +162,42 @@ func (a *app) Seal(config *fst.Config) error {
|
|||||||
return fmsg.WrapError(ErrUser,
|
return fmsg.WrapError(ErrUser,
|
||||||
fmt.Sprintf("aid %d out of range", config.Confinement.AppID))
|
fmt.Sprintf("aid %d out of range", config.Confinement.AppID))
|
||||||
}
|
}
|
||||||
seal.sys.user = appUser{
|
seal.user = appUser{
|
||||||
aid: newInt(config.Confinement.AppID),
|
aid: newInt(config.Confinement.AppID),
|
||||||
data: config.Confinement.Outer,
|
data: config.Confinement.Outer,
|
||||||
home: config.Confinement.Inner,
|
home: config.Confinement.Inner,
|
||||||
username: config.Confinement.Username,
|
username: config.Confinement.Username,
|
||||||
}
|
}
|
||||||
if seal.sys.user.username == "" {
|
if seal.user.username == "" {
|
||||||
seal.sys.user.username = "chronos"
|
seal.user.username = "chronos"
|
||||||
} else if !posixUsername.MatchString(seal.sys.user.username) ||
|
} else if !posixUsername.MatchString(seal.user.username) ||
|
||||||
len(seal.sys.user.username) >= internal.Sysconf_SC_LOGIN_NAME_MAX() {
|
len(seal.user.username) >= internal.Sysconf_SC_LOGIN_NAME_MAX() {
|
||||||
return fmsg.WrapError(ErrName,
|
return fmsg.WrapError(ErrName,
|
||||||
fmt.Sprintf("invalid user name %q", seal.sys.user.username))
|
fmt.Sprintf("invalid user name %q", seal.user.username))
|
||||||
}
|
}
|
||||||
if seal.sys.user.data == "" || !path.IsAbs(seal.sys.user.data) {
|
if seal.user.data == "" || !path.IsAbs(seal.user.data) {
|
||||||
return fmsg.WrapError(ErrHome,
|
return fmsg.WrapError(ErrHome,
|
||||||
fmt.Sprintf("invalid home directory %q", seal.sys.user.data))
|
fmt.Sprintf("invalid home directory %q", seal.user.data))
|
||||||
}
|
}
|
||||||
if seal.sys.user.home == "" {
|
if seal.user.home == "" {
|
||||||
seal.sys.user.home = seal.sys.user.data
|
seal.user.home = seal.user.data
|
||||||
}
|
}
|
||||||
|
|
||||||
// invoke fsu for full uid
|
// invoke fsu for full uid
|
||||||
if u, err := a.sys.Uid(seal.sys.user.aid.unwrap()); err != nil {
|
if u, err := a.sys.Uid(seal.user.aid.unwrap()); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
seal.sys.user.uid = newInt(u)
|
seal.user.uid = newInt(u)
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve supplementary group ids from names
|
// resolve supplementary group ids from names
|
||||||
seal.sys.user.supp = make([]string, len(config.Confinement.Groups))
|
seal.user.supp = make([]string, len(config.Confinement.Groups))
|
||||||
for i, name := range config.Confinement.Groups {
|
for i, name := range config.Confinement.Groups {
|
||||||
if g, err := a.sys.LookupGroup(name); err != nil {
|
if g, err := a.sys.LookupGroup(name); err != nil {
|
||||||
return fmsg.WrapError(err,
|
return fmsg.WrapError(err,
|
||||||
fmt.Sprintf("unknown group %q", name))
|
fmt.Sprintf("unknown group %q", name))
|
||||||
} else {
|
} else {
|
||||||
seal.sys.user.supp[i] = g.Gid
|
seal.user.supp[i] = g.Gid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,11 +274,11 @@ func (a *app) Seal(config *fst.Config) error {
|
|||||||
if b, err := config.Confinement.Sandbox.Bwrap(a.sys); err != nil {
|
if b, err := config.Confinement.Sandbox.Bwrap(a.sys); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
seal.sys.bwrap = b
|
seal.container = b
|
||||||
}
|
}
|
||||||
seal.sys.override = config.Confinement.Sandbox.Override
|
seal.override = config.Confinement.Sandbox.Override
|
||||||
if seal.sys.bwrap.SetEnv == nil {
|
if seal.container.SetEnv == nil {
|
||||||
seal.sys.bwrap.SetEnv = make(map[string]string)
|
seal.container.SetEnv = make(map[string]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// open process state store
|
// open process state store
|
||||||
@ -255,11 +287,11 @@ func (a *app) Seal(config *fst.Config) error {
|
|||||||
seal.store = state.NewMulti(seal.RunDirPath)
|
seal.store = state.NewMulti(seal.RunDirPath)
|
||||||
|
|
||||||
// initialise system interface with os uid
|
// initialise system interface with os uid
|
||||||
seal.sys.I = system.New(seal.sys.user.uid.unwrap())
|
seal.sys = system.New(seal.user.uid.unwrap())
|
||||||
seal.sys.I.IsVerbose = fmsg.Load
|
seal.sys.IsVerbose = fmsg.Load
|
||||||
seal.sys.I.Verbose = fmsg.Verbose
|
seal.sys.Verbose = fmsg.Verbose
|
||||||
seal.sys.I.Verbosef = fmsg.Verbosef
|
seal.sys.Verbosef = fmsg.Verbosef
|
||||||
seal.sys.I.WrapErr = fmsg.WrapError
|
seal.sys.WrapErr = fmsg.WrapError
|
||||||
|
|
||||||
// pass through enablements
|
// pass through enablements
|
||||||
seal.Enablements = config.Confinement.Enablements
|
seal.Enablements = config.Confinement.Enablements
|
||||||
@ -271,7 +303,7 @@ func (a *app) Seal(config *fst.Config) error {
|
|||||||
|
|
||||||
// verbose log seal information
|
// verbose log seal information
|
||||||
fmsg.Verbosef("created application seal for uid %s (%s) groups: %v, command: %s",
|
fmsg.Verbosef("created application seal for uid %s (%s) groups: %v, command: %s",
|
||||||
seal.sys.user.uid, seal.sys.user.username, config.Confinement.Groups, config.Command)
|
seal.user.uid, seal.user.username, config.Confinement.Groups, config.Command)
|
||||||
|
|
||||||
// seal app and release lock
|
// seal app and release lock
|
||||||
a.appSeal = seal
|
a.appSeal = seal
|
||||||
|
@ -68,23 +68,23 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
seal.sys.UpdatePermType(system.User, targetTmpdirParent, acl.Execute)
|
seal.sys.UpdatePermType(system.User, targetTmpdirParent, acl.Execute)
|
||||||
|
|
||||||
// ensure child tmpdir (e.g. `/tmp/fortify.%d/tmpdir/%d`)
|
// ensure child tmpdir (e.g. `/tmp/fortify.%d/tmpdir/%d`)
|
||||||
targetTmpdir := path.Join(targetTmpdirParent, seal.sys.user.aid.String())
|
targetTmpdir := path.Join(targetTmpdirParent, seal.user.aid.String())
|
||||||
seal.sys.Ensure(targetTmpdir, 01700)
|
seal.sys.Ensure(targetTmpdir, 01700)
|
||||||
seal.sys.UpdatePermType(system.User, targetTmpdir, acl.Read, acl.Write, acl.Execute)
|
seal.sys.UpdatePermType(system.User, targetTmpdir, acl.Read, acl.Write, acl.Execute)
|
||||||
seal.sys.bwrap.Bind(targetTmpdir, "/tmp", false, true)
|
seal.container.Bind(targetTmpdir, "/tmp", false, true)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
XDG runtime directory
|
XDG runtime directory
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// mount tmpfs on inner runtime (e.g. `/run/user/%d`)
|
// mount tmpfs on inner runtime (e.g. `/run/user/%d`)
|
||||||
seal.sys.bwrap.Tmpfs("/run/user", 1*1024*1024)
|
seal.container.Tmpfs("/run/user", 1*1024*1024)
|
||||||
seal.sys.bwrap.Tmpfs(seal.sys.runtime, 8*1024*1024)
|
seal.container.Tmpfs(seal.innerRuntimeDir, 8*1024*1024)
|
||||||
|
|
||||||
// point to inner runtime path `/run/user/%d`
|
// point to inner runtime path `/run/user/%d`
|
||||||
seal.sys.bwrap.SetEnv[xdgRuntimeDir] = seal.sys.runtime
|
seal.container.SetEnv[xdgRuntimeDir] = seal.innerRuntimeDir
|
||||||
seal.sys.bwrap.SetEnv[xdgSessionClass] = "user"
|
seal.container.SetEnv[xdgSessionClass] = "user"
|
||||||
seal.sys.bwrap.SetEnv[xdgSessionType] = "tty"
|
seal.container.SetEnv[xdgSessionType] = "tty"
|
||||||
|
|
||||||
// ensure RunDir (e.g. `/run/user/%d/fortify`)
|
// ensure RunDir (e.g. `/run/user/%d/fortify`)
|
||||||
seal.sys.Ensure(seal.RunDirPath, 0700)
|
seal.sys.Ensure(seal.RunDirPath, 0700)
|
||||||
@ -106,29 +106,29 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
// look up shell
|
// look up shell
|
||||||
sh := "/bin/sh"
|
sh := "/bin/sh"
|
||||||
if s, ok := os.LookupEnv(shell); ok {
|
if s, ok := os.LookupEnv(shell); ok {
|
||||||
seal.sys.bwrap.SetEnv[shell] = s
|
seal.container.SetEnv[shell] = s
|
||||||
sh = s
|
sh = s
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind home directory
|
// bind home directory
|
||||||
homeDir := "/var/empty"
|
homeDir := "/var/empty"
|
||||||
if seal.sys.user.home != "" {
|
if seal.user.home != "" {
|
||||||
homeDir = seal.sys.user.home
|
homeDir = seal.user.home
|
||||||
}
|
}
|
||||||
username := "chronos"
|
username := "chronos"
|
||||||
if seal.sys.user.username != "" {
|
if seal.user.username != "" {
|
||||||
username = seal.sys.user.username
|
username = seal.user.username
|
||||||
}
|
}
|
||||||
seal.sys.bwrap.Bind(seal.sys.user.data, homeDir, false, true)
|
seal.container.Bind(seal.user.data, homeDir, false, true)
|
||||||
seal.sys.bwrap.Chdir = homeDir
|
seal.container.Chdir = homeDir
|
||||||
seal.sys.bwrap.SetEnv["HOME"] = homeDir
|
seal.container.SetEnv["HOME"] = homeDir
|
||||||
seal.sys.bwrap.SetEnv["USER"] = username
|
seal.container.SetEnv["USER"] = username
|
||||||
|
|
||||||
// generate /etc/passwd and /etc/group
|
// generate /etc/passwd and /etc/group
|
||||||
seal.sys.bwrap.CopyBind("/etc/passwd",
|
seal.container.CopyBind("/etc/passwd",
|
||||||
[]byte(username+":x:"+seal.sys.mapuid.String()+":"+seal.sys.mapuid.String()+":Fortify:"+homeDir+":"+sh+"\n"))
|
[]byte(username+":x:"+seal.mapuid.String()+":"+seal.mapuid.String()+":Fortify:"+homeDir+":"+sh+"\n"))
|
||||||
seal.sys.bwrap.CopyBind("/etc/group",
|
seal.container.CopyBind("/etc/group",
|
||||||
[]byte("fortify:x:"+seal.sys.mapuid.String()+":\n"))
|
[]byte("fortify:x:"+seal.mapuid.String()+":\n"))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Display servers
|
Display servers
|
||||||
@ -136,7 +136,7 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
|
|
||||||
// pass $TERM to launcher
|
// pass $TERM to launcher
|
||||||
if t, ok := os.LookupEnv(term); ok {
|
if t, ok := os.LookupEnv(term); ok {
|
||||||
seal.sys.bwrap.SetEnv[term] = t
|
seal.container.SetEnv[term] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up wayland
|
// set up wayland
|
||||||
@ -151,8 +151,8 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
socketPath = name
|
socketPath = name
|
||||||
}
|
}
|
||||||
|
|
||||||
innerPath := path.Join(seal.sys.runtime, wl.FallbackName)
|
innerPath := path.Join(seal.innerRuntimeDir, wl.FallbackName)
|
||||||
seal.sys.bwrap.SetEnv[wl.WaylandDisplay] = wl.FallbackName
|
seal.container.SetEnv[wl.WaylandDisplay] = wl.FallbackName
|
||||||
|
|
||||||
if !seal.directWayland { // set up security-context-v1
|
if !seal.directWayland { // set up security-context-v1
|
||||||
socketDir := path.Join(seal.SharePath, "wayland")
|
socketDir := path.Join(seal.SharePath, "wayland")
|
||||||
@ -163,11 +163,11 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
// use instance ID in case app id is not set
|
// use instance ID in case app id is not set
|
||||||
appID = "uk.gensokyo.fortify." + seal.id
|
appID = "uk.gensokyo.fortify." + seal.id
|
||||||
}
|
}
|
||||||
seal.sys.Wayland(&seal.sys.sp, outerPath, socketPath, appID, seal.id)
|
seal.sys.Wayland(&seal.bwrapSync, outerPath, socketPath, appID, seal.id)
|
||||||
seal.sys.bwrap.Bind(outerPath, innerPath)
|
seal.container.Bind(outerPath, innerPath)
|
||||||
} else { // bind mount wayland socket (insecure)
|
} else { // bind mount wayland socket (insecure)
|
||||||
fmsg.Verbose("direct wayland access, PROCEED WITH CAUTION")
|
fmsg.Verbose("direct wayland access, PROCEED WITH CAUTION")
|
||||||
seal.sys.bwrap.Bind(socketPath, innerPath)
|
seal.container.Bind(socketPath, innerPath)
|
||||||
|
|
||||||
// ensure Wayland socket ACL (e.g. `/run/user/%d/wayland-%d`)
|
// ensure Wayland socket ACL (e.g. `/run/user/%d/wayland-%d`)
|
||||||
seal.sys.UpdatePermType(system.EWayland, socketPath, acl.Read, acl.Write, acl.Execute)
|
seal.sys.UpdatePermType(system.EWayland, socketPath, acl.Read, acl.Write, acl.Execute)
|
||||||
@ -181,9 +181,9 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
return fmsg.WrapError(ErrXDisplay,
|
return fmsg.WrapError(ErrXDisplay,
|
||||||
"DISPLAY is not set")
|
"DISPLAY is not set")
|
||||||
} else {
|
} else {
|
||||||
seal.sys.ChangeHosts("#" + seal.sys.user.uid.String())
|
seal.sys.ChangeHosts("#" + seal.user.uid.String())
|
||||||
seal.sys.bwrap.SetEnv[display] = d
|
seal.container.SetEnv[display] = d
|
||||||
seal.sys.bwrap.Bind("/tmp/.X11-unix", "/tmp/.X11-unix")
|
seal.container.Bind("/tmp/.X11-unix", "/tmp/.X11-unix")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,10 +221,10 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
|
|
||||||
// hard link pulse socket into target-executable share
|
// hard link pulse socket into target-executable share
|
||||||
psi := path.Join(seal.shareLocal, "pulse")
|
psi := path.Join(seal.shareLocal, "pulse")
|
||||||
p := path.Join(seal.sys.runtime, "pulse", "native")
|
p := path.Join(seal.innerRuntimeDir, "pulse", "native")
|
||||||
seal.sys.Link(ps, psi)
|
seal.sys.Link(ps, psi)
|
||||||
seal.sys.bwrap.Bind(psi, p)
|
seal.container.Bind(psi, p)
|
||||||
seal.sys.bwrap.SetEnv[pulseServer] = "unix:" + p
|
seal.container.SetEnv[pulseServer] = "unix:" + p
|
||||||
|
|
||||||
// publish current user's pulse cookie for target user
|
// publish current user's pulse cookie for target user
|
||||||
if src, err := discoverPulseCookie(os); err != nil {
|
if src, err := discoverPulseCookie(os); err != nil {
|
||||||
@ -232,9 +232,9 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
fmsg.Verbose(strings.TrimSpace(err.(*fmsg.BaseError).Message()))
|
fmsg.Verbose(strings.TrimSpace(err.(*fmsg.BaseError).Message()))
|
||||||
} else {
|
} else {
|
||||||
innerDst := fst.Tmp + "/pulse-cookie"
|
innerDst := fst.Tmp + "/pulse-cookie"
|
||||||
seal.sys.bwrap.SetEnv[pulseCookie] = innerDst
|
seal.container.SetEnv[pulseCookie] = innerDst
|
||||||
payload := new([]byte)
|
payload := new([]byte)
|
||||||
seal.sys.bwrap.CopyBindRef(innerDst, &payload)
|
seal.container.CopyBindRef(innerDst, &payload)
|
||||||
seal.sys.CopyFile(payload, src, 256, 256)
|
seal.sys.CopyFile(payload, src, 256, 256)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,14 +260,14 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// share proxy sockets
|
// share proxy sockets
|
||||||
sessionInner := path.Join(seal.sys.runtime, "bus")
|
sessionInner := path.Join(seal.innerRuntimeDir, "bus")
|
||||||
seal.sys.bwrap.SetEnv[dbusSessionBusAddress] = "unix:path=" + sessionInner
|
seal.container.SetEnv[dbusSessionBusAddress] = "unix:path=" + sessionInner
|
||||||
seal.sys.bwrap.Bind(sessionPath, sessionInner)
|
seal.container.Bind(sessionPath, sessionInner)
|
||||||
seal.sys.UpdatePerm(sessionPath, acl.Read, acl.Write)
|
seal.sys.UpdatePerm(sessionPath, acl.Read, acl.Write)
|
||||||
if bus[1] != nil {
|
if bus[1] != nil {
|
||||||
systemInner := "/run/dbus/system_bus_socket"
|
systemInner := "/run/dbus/system_bus_socket"
|
||||||
seal.sys.bwrap.SetEnv[dbusSystemBusAddress] = "unix:path=" + systemInner
|
seal.container.SetEnv[dbusSystemBusAddress] = "unix:path=" + systemInner
|
||||||
seal.sys.bwrap.Bind(systemPath, systemInner)
|
seal.container.Bind(systemPath, systemInner)
|
||||||
seal.sys.UpdatePerm(systemPath, acl.Read, acl.Write)
|
seal.sys.UpdatePerm(systemPath, acl.Read, acl.Write)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,14 +276,14 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os sys.State) error {
|
|||||||
Miscellaneous
|
Miscellaneous
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// queue overriding tmpfs at the end of seal.sys.bwrap.Filesystem
|
// queue overriding tmpfs at the end of seal.container.Filesystem
|
||||||
for _, dest := range seal.sys.override {
|
for _, dest := range seal.override {
|
||||||
seal.sys.bwrap.Tmpfs(dest, 8*1024)
|
seal.container.Tmpfs(dest, 8*1024)
|
||||||
}
|
}
|
||||||
|
|
||||||
// mount fortify in sandbox for init
|
// mount fortify in sandbox for init
|
||||||
seal.sys.bwrap.Bind(os.MustExecutable(), path.Join(fst.Tmp, "sbin/fortify"))
|
seal.container.Bind(os.MustExecutable(), path.Join(fst.Tmp, "sbin/fortify"))
|
||||||
seal.sys.bwrap.Symlink("fortify", path.Join(fst.Tmp, "sbin/init"))
|
seal.container.Symlink("fortify", path.Join(fst.Tmp, "sbin/init"))
|
||||||
|
|
||||||
// append extra perms
|
// append extra perms
|
||||||
for _, p := range seal.extraPerms {
|
for _, p := range seal.extraPerms {
|
||||||
|
@ -51,15 +51,15 @@ func (a *app) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
if err := a.appSeal.sys.Commit(ctx); err != nil {
|
if err := a.appSeal.sys.Commit(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
a.appSeal.sys.needRevert = true
|
a.appSeal.needRevert = true
|
||||||
|
|
||||||
// start shim via manager
|
// start shim via manager
|
||||||
a.shim = new(shim.Shim)
|
a.shim = new(shim.Shim)
|
||||||
waitErr := make(chan error, 1)
|
waitErr := make(chan error, 1)
|
||||||
if startTime, err := a.shim.Start(
|
if startTime, err := a.shim.Start(
|
||||||
a.appSeal.sys.user.aid.String(),
|
a.appSeal.user.aid.String(),
|
||||||
a.appSeal.sys.user.supp,
|
a.appSeal.user.supp,
|
||||||
a.appSeal.sys.sp,
|
a.appSeal.bwrapSync,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
@ -80,8 +80,8 @@ func (a *app) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
if err = a.shim.Serve(shimSetupCtx, &shim.Payload{
|
if err = a.shim.Serve(shimSetupCtx, &shim.Payload{
|
||||||
Argv: a.appSeal.command,
|
Argv: a.appSeal.command,
|
||||||
Exec: shimExec,
|
Exec: shimExec,
|
||||||
Bwrap: a.appSeal.sys.bwrap,
|
Bwrap: a.appSeal.container,
|
||||||
Home: a.appSeal.sys.user.data,
|
Home: a.appSeal.user.data,
|
||||||
|
|
||||||
Verbose: fmsg.Load(),
|
Verbose: fmsg.Load(),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -97,10 +97,10 @@ func (a *app) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
|
|
||||||
// register process state
|
// register process state
|
||||||
var err0 = new(StateStoreError)
|
var err0 = new(StateStoreError)
|
||||||
err0.Inner, err0.DoErr = a.appSeal.store.Do(a.appSeal.sys.user.aid.unwrap(), func(c state.Cursor) {
|
err0.Inner, err0.DoErr = a.appSeal.store.Do(a.appSeal.user.aid.unwrap(), func(c state.Cursor) {
|
||||||
err0.InnerErr = c.Save(&sd, a.appSeal.ct)
|
err0.InnerErr = c.Save(&sd, a.appSeal.ct)
|
||||||
})
|
})
|
||||||
a.appSeal.sys.saveState = true
|
a.appSeal.stateInStore = true
|
||||||
if err = err0.equiv("cannot save process state:"); err != nil {
|
if err = err0.equiv("cannot save process state:"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -147,10 +147,10 @@ func (a *app) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
|
|
||||||
// update store and revert app setup transaction
|
// update store and revert app setup transaction
|
||||||
e := new(StateStoreError)
|
e := new(StateStoreError)
|
||||||
e.Inner, e.DoErr = a.appSeal.store.Do(a.appSeal.sys.user.aid.unwrap(), func(b state.Cursor) {
|
e.Inner, e.DoErr = a.appSeal.store.Do(a.appSeal.user.aid.unwrap(), func(b state.Cursor) {
|
||||||
e.InnerErr = func() error {
|
e.InnerErr = func() error {
|
||||||
// destroy defunct state entry
|
// destroy defunct state entry
|
||||||
if cmd := a.shim.Unwrap(); cmd != nil && a.appSeal.sys.saveState {
|
if cmd := a.shim.Unwrap(); cmd != nil && a.appSeal.stateInStore {
|
||||||
if err := b.Destroy(a.id.unwrap()); err != nil {
|
if err := b.Destroy(a.id.unwrap()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ func (a *app) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.appSeal.sys.needRevert {
|
if a.appSeal.needRevert {
|
||||||
if err := a.appSeal.sys.Revert(ec); err != nil {
|
if err := a.appSeal.sys.Revert(ec); err != nil {
|
||||||
return err.(RevertCompoundError)
|
return err.(RevertCompoundError)
|
||||||
}
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
package app
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
|
||||||
"git.gensokyo.uk/security/fortify/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
// appSealSys encapsulates app seal behaviour with OS interactions
|
|
||||||
type appSealSys struct {
|
|
||||||
bwrap *bwrap.Config
|
|
||||||
// bwrap sync fd
|
|
||||||
sp *os.File
|
|
||||||
// paths to override by mounting tmpfs over them
|
|
||||||
override []string
|
|
||||||
|
|
||||||
// default formatted XDG_RUNTIME_DIR of User
|
|
||||||
runtime string
|
|
||||||
// target user sealed from config
|
|
||||||
user appUser
|
|
||||||
|
|
||||||
// mapped uid and gid in user namespace
|
|
||||||
mapuid *stringPair[int]
|
|
||||||
|
|
||||||
needRevert bool
|
|
||||||
saveState bool
|
|
||||||
*system.I
|
|
||||||
|
|
||||||
// protected by upstream mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
type appUser struct {
|
|
||||||
// application id
|
|
||||||
aid *stringPair[int]
|
|
||||||
// target uid resolved by fid:aid
|
|
||||||
uid *stringPair[int]
|
|
||||||
|
|
||||||
// supplementary group ids
|
|
||||||
supp []string
|
|
||||||
|
|
||||||
// home directory host path
|
|
||||||
data string
|
|
||||||
// app user home directory
|
|
||||||
home string
|
|
||||||
// passwd database username
|
|
||||||
username string
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user