Place the host UDS mounting behind --fsgofer-host-uds-allowed.

This commit allows the use of the `--fsgofer-host-uds-allowed` flag to 
enable mounting sockets and add the appropriate seccomp filters.
This commit is contained in:
Robert Tonic 2019-09-19 12:37:15 -04:00
parent c2ae77a607
commit ac38a7ead0
7 changed files with 98 additions and 54 deletions

View File

@ -138,6 +138,9 @@ type Config struct {
// Overlay is whether to wrap the root filesystem in an overlay.
Overlay bool
// fsGoferHostUDSAllowed enables the gofer to mount a host UDS
FSGoferHostUDSAllowed bool
// Network indicates what type of network to use.
Network NetworkType

View File

@ -59,6 +59,7 @@ type Gofer struct {
bundleDir string
ioFDs intFlags
applyCaps bool
hostUDSAllowed bool
setUpRoot bool
panicOnWrite bool
@ -86,6 +87,7 @@ func (g *Gofer) SetFlags(f *flag.FlagSet) {
f.StringVar(&g.bundleDir, "bundle", "", "path to the root of the bundle directory, defaults to the current directory")
f.Var(&g.ioFDs, "io-fds", "list of FDs to connect 9P servers. They must follow this order: root first, then mounts as defined in the spec")
f.BoolVar(&g.applyCaps, "apply-caps", true, "if true, apply capabilities to restrict what the Gofer process can do")
f.BoolVar(&g.hostUDSAllowed, "host-uds-allowed", false, "if true, allow the Gofer to mount a host UDS")
f.BoolVar(&g.panicOnWrite, "panic-on-write", false, "if true, panics on attempts to write to RO mounts. RW mounts are unnaffected")
f.BoolVar(&g.setUpRoot, "setup-root", true, "if true, set up an empty root for the process")
f.IntVar(&g.specFD, "spec-fd", -1, "required fd with the container spec")
@ -182,6 +184,7 @@ func (g *Gofer) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
cfg := fsgofer.Config{
ROMount: isReadonlyMount(m.Options),
PanicOnWrite: g.panicOnWrite,
HostUDSAllowed: g.hostUDSAllowed,
}
ap, err := fsgofer.NewAttachPoint(m.Destination, cfg)
if err != nil {
@ -200,9 +203,15 @@ func (g *Gofer) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
Fatalf("too many FDs passed for mounts. mounts: %d, FDs: %d", mountIdx, len(g.ioFDs))
}
if g.hostUDSAllowed {
if err := filter.InstallUDS(); err != nil {
Fatalf("installing UDS seccomp filters: %v", err)
}
} else {
if err := filter.Install(); err != nil {
Fatalf("installing seccomp filters: %v", err)
}
}
runServers(ats, g.ioFDs)
return subcommands.ExitSuccess

View File

@ -941,6 +941,11 @@ func (c *Container) createGoferProcess(spec *specs.Spec, conf *boot.Config, bund
args = append(args, "--panic-on-write=true")
}
// Add support for mounting host UDS in the gofer
if conf.FSGoferHostUDSAllowed {
args = append(args, "--host-uds-allowed=true")
}
// Open the spec file to donate to the sandbox.
specFile, err := specutils.OpenSpec(bundleDir)
if err != nil {

View File

@ -26,16 +26,6 @@ import (
// allowedSyscalls is the set of syscalls executed by the gofer.
var allowedSyscalls = seccomp.SyscallRules{
syscall.SYS_ACCEPT: {},
syscall.SYS_SOCKET: []seccomp.Rule{
{
seccomp.AllowValue(syscall.AF_UNIX),
},
},
syscall.SYS_CONNECT: []seccomp.Rule{
{
seccomp.AllowAny{},
},
},
syscall.SYS_ARCH_PRCTL: []seccomp.Rule{
{seccomp.AllowValue(linux.ARCH_GET_FS)},
{seccomp.AllowValue(linux.ARCH_SET_FS)},
@ -194,3 +184,16 @@ var allowedSyscalls = seccomp.SyscallRules{
syscall.SYS_UTIMENSAT: {},
syscall.SYS_WRITE: {},
}
var udsSyscalls = seccomp.SyscallRules{
syscall.SYS_SOCKET: []seccomp.Rule{
{
seccomp.AllowValue(syscall.AF_UNIX),
},
},
syscall.SYS_CONNECT: []seccomp.Rule{
{
seccomp.AllowAny{},
},
},
}

View File

@ -31,3 +31,15 @@ func Install() error {
return seccomp.Install(s)
}
// InstallUDS installs the standard Gofer seccomp filters along with filters
// allowing the gofer to connect to a host UDS.
func InstallUDS() error {
// Use the base syscall
s := allowedSyscalls
// Add additional filters required for connecting to the host's sockets.
s.Merge(udsSyscalls)
return seccomp.Install(s)
}

View File

@ -85,6 +85,9 @@ type Config struct {
// PanicOnWrite panics on attempts to write to RO mounts.
PanicOnWrite bool
// HostUDS prevents
HostUDSAllowed bool
}
type attachPoint struct {
@ -128,12 +131,21 @@ func (a *attachPoint) Attach() (p9.File, error) {
return nil, fmt.Errorf("stat file %q, err: %v", a.prefix, err)
}
// Acquire the attach point lock
a.attachedMu.Lock()
defer a.attachedMu.Unlock()
// Hold the file descriptor we are converting into a p9.File
var f *fd.FD
// Apply the S_IFMT bitmask so we can detect file type appropriately
switch fmtStat := stat.Mode & syscall.S_IFMT; {
case fmtStat == syscall.S_IFSOCK:
// Check to see if the CLI option has been set to allow the UDS mount
if !a.conf.HostUDSAllowed {
return nil, fmt.Errorf("host UDS support is disabled")
}
// Attempt to open a connection. Bubble up the failures.
f, err = fd.OpenUnix(a.prefix)
if err != nil {
@ -144,7 +156,7 @@ func (a *attachPoint) Attach() (p9.File, error) {
// Default to Read/Write permissions.
mode := syscall.O_RDWR
// If the configuration is Read Only & the mount point is a directory,
// If the configuration is Read Only or the mount point is a directory,
// set the mode to Read Only.
if a.conf.ROMount || fmtStat == syscall.S_IFDIR {
mode = syscall.O_RDONLY
@ -157,9 +169,7 @@ func (a *attachPoint) Attach() (p9.File, error) {
}
}
// Close the connection if the UDS is already attached.
a.attachedMu.Lock()
defer a.attachedMu.Unlock()
// Close the connection if already attached.
if a.attached {
f.Close()
return nil, fmt.Errorf("attach point already attached, prefix: %s", a.prefix)

View File

@ -67,6 +67,7 @@ var (
network = flag.String("network", "sandbox", "specifies which network to use: sandbox (default), host, none. Using network inside the sandbox is more secure because it's isolated from the host network.")
gso = flag.Bool("gso", true, "enable generic segmenation offload")
fileAccess = flag.String("file-access", "exclusive", "specifies which filesystem to use for the root mount: exclusive (default), shared. Volume mounts are always shared.")
fsGoferHostUDSAllowed = flag.Bool("fsgofer-host-uds-allowed", false, "Allow the gofer to mount Unix Domain Sockets.")
overlay = flag.Bool("overlay", false, "wrap filesystem mounts with writable overlay. All modifications are stored in memory inside the sandbox.")
watchdogAction = flag.String("watchdog-action", "log", "sets what action the watchdog takes when triggered: log (default), panic.")
panicSignal = flag.Int("panic-signal", -1, "register signal handling that panics. Usually set to SIGUSR2(12) to troubleshoot hangs. -1 disables it.")
@ -178,6 +179,7 @@ func main() {
DebugLog: *debugLog,
DebugLogFormat: *debugLogFormat,
FileAccess: fsAccess,
FSGoferHostUDSAllowed: *fsGoferHostUDSAllowed,
Overlay: *overlay,
Network: netType,
GSO: *gso,