app: extra acl entries from configuration
Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
c70f0612ad
commit
847b667489
@ -35,6 +35,8 @@ type ConfinementConfig struct {
|
|||||||
Outer string `json:"home"`
|
Outer string `json:"home"`
|
||||||
// bwrap sandbox confinement configuration
|
// bwrap sandbox confinement configuration
|
||||||
Sandbox *SandboxConfig `json:"sandbox"`
|
Sandbox *SandboxConfig `json:"sandbox"`
|
||||||
|
// extra acl entries to append
|
||||||
|
ExtraPerms []*ExtraPermConfig `json:"extra_perms,omitempty"`
|
||||||
|
|
||||||
// reference to a system D-Bus proxy configuration,
|
// reference to a system D-Bus proxy configuration,
|
||||||
// nil value disables system bus proxy
|
// nil value disables system bus proxy
|
||||||
@ -78,6 +80,29 @@ type SandboxConfig struct {
|
|||||||
Override []string `json:"override"`
|
Override []string `json:"override"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExtraPermConfig struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Read bool `json:"r,omitempty"`
|
||||||
|
Write bool `json:"w,omitempty"`
|
||||||
|
Execute bool `json:"x,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ExtraPermConfig) String() string {
|
||||||
|
buf := make([]byte, 0, 4+len(e.Path))
|
||||||
|
buf = append(buf, '-', '-', '-', ':')
|
||||||
|
buf = append(buf, []byte(e.Path)...)
|
||||||
|
if e.Read {
|
||||||
|
buf[0] = 'r'
|
||||||
|
}
|
||||||
|
if e.Write {
|
||||||
|
buf[1] = 'w'
|
||||||
|
}
|
||||||
|
if e.Execute {
|
||||||
|
buf[2] = 'x'
|
||||||
|
}
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
type FilesystemConfig struct {
|
type FilesystemConfig struct {
|
||||||
// mount point in sandbox, same as src if empty
|
// mount point in sandbox, same as src if empty
|
||||||
Dst string `json:"dst,omitempty"`
|
Dst string `json:"dst,omitempty"`
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"git.gensokyo.uk/security/fortify/acl"
|
||||||
"git.gensokyo.uk/security/fortify/dbus"
|
"git.gensokyo.uk/security/fortify/dbus"
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
@ -48,6 +49,8 @@ type appSeal struct {
|
|||||||
et system.Enablements
|
et system.Enablements
|
||||||
// wayland socket direct access
|
// wayland socket direct access
|
||||||
directWayland bool
|
directWayland bool
|
||||||
|
// extra UpdatePerm ops
|
||||||
|
extraPerms []*sealedExtraPerm
|
||||||
|
|
||||||
// prevents sharing from happening twice
|
// prevents sharing from happening twice
|
||||||
shared bool
|
shared bool
|
||||||
@ -59,6 +62,11 @@ type appSeal struct {
|
|||||||
// protected by upstream mutex
|
// protected by upstream mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sealedExtraPerm struct {
|
||||||
|
name string
|
||||||
|
perms acl.Perms
|
||||||
|
}
|
||||||
|
|
||||||
// Seal seals the app launch context
|
// Seal seals the app launch context
|
||||||
func (a *app) Seal(config *fst.Config) error {
|
func (a *app) Seal(config *fst.Config) error {
|
||||||
a.lock.Lock()
|
a.lock.Lock()
|
||||||
@ -100,46 +108,66 @@ func (a *app) Seal(config *fst.Config) error {
|
|||||||
if config.Confinement.AppID < 0 || config.Confinement.AppID > 9999 {
|
if config.Confinement.AppID < 0 || config.Confinement.AppID > 9999 {
|
||||||
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{
|
||||||
|
aid: config.Confinement.AppID,
|
||||||
|
as: strconv.Itoa(config.Confinement.AppID),
|
||||||
|
data: config.Confinement.Outer,
|
||||||
|
home: config.Confinement.Inner,
|
||||||
|
username: config.Confinement.Username,
|
||||||
|
}
|
||||||
|
if seal.sys.user.username == "" {
|
||||||
|
seal.sys.user.username = "chronos"
|
||||||
|
} else if !posixUsername.MatchString(seal.sys.user.username) {
|
||||||
|
return fmsg.WrapError(ErrName,
|
||||||
|
fmt.Sprintf("invalid user name %q", seal.sys.user.username))
|
||||||
|
}
|
||||||
|
if seal.sys.user.data == "" || !path.IsAbs(seal.sys.user.data) {
|
||||||
|
return fmsg.WrapError(ErrHome,
|
||||||
|
fmt.Sprintf("invalid home directory %q", seal.sys.user.data))
|
||||||
|
}
|
||||||
|
if seal.sys.user.home == "" {
|
||||||
|
seal.sys.user.home = seal.sys.user.data
|
||||||
|
}
|
||||||
|
|
||||||
|
// invoke fsu for full uid
|
||||||
|
if u, err := a.os.Uid(seal.sys.user.aid); err != nil {
|
||||||
|
return fmsg.WrapErrorSuffix(err,
|
||||||
|
"cannot obtain uid from fsu:")
|
||||||
} else {
|
} else {
|
||||||
seal.sys.user = appUser{
|
seal.sys.user.uid = u
|
||||||
aid: config.Confinement.AppID,
|
seal.sys.user.us = strconv.Itoa(u)
|
||||||
as: strconv.Itoa(config.Confinement.AppID),
|
}
|
||||||
data: config.Confinement.Outer,
|
|
||||||
home: config.Confinement.Inner,
|
|
||||||
username: config.Confinement.Username,
|
|
||||||
}
|
|
||||||
if seal.sys.user.username == "" {
|
|
||||||
seal.sys.user.username = "chronos"
|
|
||||||
} else if !posixUsername.MatchString(seal.sys.user.username) {
|
|
||||||
return fmsg.WrapError(ErrName,
|
|
||||||
fmt.Sprintf("invalid user name %q", seal.sys.user.username))
|
|
||||||
}
|
|
||||||
if seal.sys.user.data == "" || !path.IsAbs(seal.sys.user.data) {
|
|
||||||
return fmsg.WrapError(ErrHome,
|
|
||||||
fmt.Sprintf("invalid home directory %q", seal.sys.user.data))
|
|
||||||
}
|
|
||||||
if seal.sys.user.home == "" {
|
|
||||||
seal.sys.user.home = seal.sys.user.data
|
|
||||||
}
|
|
||||||
|
|
||||||
// invoke fsu for full uid
|
// resolve supplementary group ids from names
|
||||||
if u, err := a.os.Uid(seal.sys.user.aid); err != nil {
|
seal.sys.user.supp = make([]string, len(config.Confinement.Groups))
|
||||||
return fmsg.WrapErrorSuffix(err,
|
for i, name := range config.Confinement.Groups {
|
||||||
"cannot obtain uid from fsu:")
|
if g, err := a.os.LookupGroup(name); err != nil {
|
||||||
|
return fmsg.WrapError(err,
|
||||||
|
fmt.Sprintf("unknown group %q", name))
|
||||||
} else {
|
} else {
|
||||||
seal.sys.user.uid = u
|
seal.sys.user.supp[i] = g.Gid
|
||||||
seal.sys.user.us = strconv.Itoa(u)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build extra perms
|
||||||
|
seal.extraPerms = make([]*sealedExtraPerm, len(config.Confinement.ExtraPerms))
|
||||||
|
for i, p := range config.Confinement.ExtraPerms {
|
||||||
|
if p == nil {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve supplementary group ids from names
|
seal.extraPerms[i] = new(sealedExtraPerm)
|
||||||
seal.sys.user.supp = make([]string, len(config.Confinement.Groups))
|
seal.extraPerms[i].name = p.Path
|
||||||
for i, name := range config.Confinement.Groups {
|
seal.extraPerms[i].perms = make(acl.Perms, 0, 3)
|
||||||
if g, err := a.os.LookupGroup(name); err != nil {
|
if p.Read {
|
||||||
return fmsg.WrapError(err,
|
seal.extraPerms[i].perms = append(seal.extraPerms[i].perms, acl.Read)
|
||||||
fmt.Sprintf("unknown group %q", name))
|
}
|
||||||
} else {
|
if p.Write {
|
||||||
seal.sys.user.supp[i] = g.Gid
|
seal.extraPerms[i].perms = append(seal.extraPerms[i].perms, acl.Write)
|
||||||
}
|
}
|
||||||
|
if p.Execute {
|
||||||
|
seal.extraPerms[i].perms = append(seal.extraPerms[i].perms, acl.Execute)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +292,14 @@ func (seal *appSeal) setupShares(bus [2]*dbus.Config, os linux.System) error {
|
|||||||
seal.sys.bwrap.Tmpfs(dest, 8*1024)
|
seal.sys.bwrap.Tmpfs(dest, 8*1024)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// append extra perms
|
||||||
|
for _, p := range seal.extraPerms {
|
||||||
|
if p == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seal.sys.UpdatePermType(system.User, p.name, p.perms...)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
62
print.go
62
print.go
@ -90,33 +90,47 @@ func printShow(instance *state.State, config *fst.Config, short bool) {
|
|||||||
fmt.Fprintf(w, " Command:\t%s\n", strings.Join(config.Command, " "))
|
fmt.Fprintf(w, " Command:\t%s\n", strings.Join(config.Command, " "))
|
||||||
fmt.Fprintf(w, "\n")
|
fmt.Fprintf(w, "\n")
|
||||||
|
|
||||||
if !short && config.Confinement.Sandbox != nil && len(config.Confinement.Sandbox.Filesystem) > 0 {
|
if !short {
|
||||||
fmt.Fprintf(w, "Filesystem:\n")
|
if config.Confinement.Sandbox != nil && len(config.Confinement.Sandbox.Filesystem) > 0 {
|
||||||
for _, f := range config.Confinement.Sandbox.Filesystem {
|
fmt.Fprintf(w, "Filesystem\n")
|
||||||
if f == nil {
|
for _, f := range config.Confinement.Sandbox.Filesystem {
|
||||||
continue
|
if f == nil {
|
||||||
}
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
expr := new(strings.Builder)
|
expr := new(strings.Builder)
|
||||||
if f.Device {
|
expr.Grow(3 + len(f.Src) + 1 + len(f.Dst))
|
||||||
expr.WriteString(" d")
|
|
||||||
} else if f.Write {
|
if f.Device {
|
||||||
expr.WriteString(" w")
|
expr.WriteString(" d")
|
||||||
} else {
|
} else if f.Write {
|
||||||
expr.WriteString(" ")
|
expr.WriteString(" w")
|
||||||
|
} else {
|
||||||
|
expr.WriteString(" ")
|
||||||
|
}
|
||||||
|
if f.Must {
|
||||||
|
expr.WriteString("*")
|
||||||
|
} else {
|
||||||
|
expr.WriteString("+")
|
||||||
|
}
|
||||||
|
expr.WriteString(f.Src)
|
||||||
|
if f.Dst != "" {
|
||||||
|
expr.WriteString(":" + f.Dst)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "%s\n", expr.String())
|
||||||
}
|
}
|
||||||
if f.Must {
|
fmt.Fprintf(w, "\n")
|
||||||
expr.WriteString("*")
|
}
|
||||||
} else {
|
if len(config.Confinement.ExtraPerms) > 0 {
|
||||||
expr.WriteString("+")
|
fmt.Fprintf(w, "Extra ACL\n")
|
||||||
}
|
for _, p := range config.Confinement.ExtraPerms {
|
||||||
expr.WriteString(f.Src)
|
if p == nil {
|
||||||
if f.Dst != "" {
|
continue
|
||||||
expr.WriteString(":" + f.Dst)
|
}
|
||||||
}
|
fmt.Fprintf(w, " %s\n", p.String())
|
||||||
fmt.Fprintf(w, "%s\n", expr.String())
|
}
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printDBus := func(c *dbus.Config) {
|
printDBus := func(c *dbus.Config) {
|
||||||
|
Loading…
Reference in New Issue
Block a user