summaryrefslogtreecommitdiffhomepage
path: root/runsc/fsgofer
diff options
context:
space:
mode:
authorRobert Tonic <btonic@users.noreply.github.com>2019-07-29 14:57:14 -0700
committerRobert Tonic <btonic@users.noreply.github.com>2019-08-27 13:08:56 -0400
commitc319b360d134cff66000fd036fce8b3816c296ea (patch)
treeb0037d1a8fd29b4ec765b6e2ca08e8eb5ced81b8 /runsc/fsgofer
parentb4cdaef4a1d545867d8e34036c5ed3175e55079d (diff)
First pass at implementing Unix Domain Socket support. No tests.
This commit adds support for detecting the socket file type, connecting to a Unix Domain Socket, and providing bidirectional communication (without file descriptor transfer support).
Diffstat (limited to 'runsc/fsgofer')
-rw-r--r--runsc/fsgofer/filter/config.go28
-rw-r--r--runsc/fsgofer/fsgofer.go73
2 files changed, 80 insertions, 21 deletions
diff --git a/runsc/fsgofer/filter/config.go b/runsc/fsgofer/filter/config.go
index 8ddfa77d6..71f387bd0 100644
--- a/runsc/fsgofer/filter/config.go
+++ b/runsc/fsgofer/filter/config.go
@@ -26,6 +26,31 @@ 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_SETSOCKOPT: []seccomp.Rule{
+ {
+ seccomp.AllowAny{},
+ },
+ },
+ syscall.SYS_GETSOCKNAME: []seccomp.Rule{
+ {
+ seccomp.AllowAny{},
+ },
+ },
+ syscall.SYS_GETPEERNAME: []seccomp.Rule{
+ {
+ seccomp.AllowAny{},
+ },
+ },
syscall.SYS_ARCH_PRCTL: []seccomp.Rule{
{seccomp.AllowValue(linux.ARCH_GET_FS)},
{seccomp.AllowValue(linux.ARCH_SET_FS)},
@@ -83,6 +108,9 @@ var allowedSyscalls = seccomp.SyscallRules{
seccomp.AllowAny{},
seccomp.AllowValue(syscall.F_GETFD),
},
+ {
+ seccomp.AllowAny{},
+ },
},
syscall.SYS_FSTAT: {},
syscall.SYS_FSTATFS: {},
diff --git a/runsc/fsgofer/fsgofer.go b/runsc/fsgofer/fsgofer.go
index 7c4d2b94e..3a78d20a3 100644
--- a/runsc/fsgofer/fsgofer.go
+++ b/runsc/fsgofer/fsgofer.go
@@ -54,6 +54,7 @@ const (
regular fileType = iota
directory
symlink
+ socket
unknown
)
@@ -66,6 +67,8 @@ func (f fileType) String() string {
return "directory"
case symlink:
return "symlink"
+ case socket:
+ return "socket"
}
return "unknown"
}
@@ -124,30 +127,56 @@ func (a *attachPoint) Attach() (p9.File, error) {
if err != nil {
return nil, fmt.Errorf("stat file %q, err: %v", a.prefix, err)
}
- mode := syscall.O_RDWR
- if a.conf.ROMount || (stat.Mode&syscall.S_IFMT) == syscall.S_IFDIR {
- mode = syscall.O_RDONLY
- }
- // Open the root directory.
- f, err := fd.Open(a.prefix, openFlags|mode, 0)
- if err != nil {
- return nil, fmt.Errorf("unable to open file %q, err: %v", a.prefix, err)
- }
+ // Apply the S_IFMT bitmask so we can detect file type appropriately
+ fmtStat := stat.Mode & syscall.S_IFMT
- a.attachedMu.Lock()
- defer a.attachedMu.Unlock()
- if a.attached {
- f.Close()
- return nil, fmt.Errorf("attach point already attached, prefix: %s", a.prefix)
- }
+ switch fmtStat{
+ case syscall.S_IFSOCK:
+ // Attempt to open a connection. Bubble up the failures.
+ f, err := fd.OpenUnix(a.prefix); if err != nil {
+ return nil, err
+ }
- rv, err := newLocalFile(a, f, a.prefix, stat)
- if err != nil {
- return nil, err
+ // Close the connection if the UDS is already attached.
+ a.attachedMu.Lock()
+ defer a.attachedMu.Unlock()
+ if a.attached {
+ f.Close()
+ return nil, fmt.Errorf("attach point already attached, prefix: %s", a.prefix)
+ }
+ a.attached = true
+
+ // Return a localFile object to the caller with the UDS FD included.
+ return newLocalFile(a, f, a.prefix, stat)
+
+ default:
+ // Default to Read/Write permissions.
+ mode := syscall.O_RDWR
+ // If the configuration is Read Only & the mount point is a directory,
+ // set the mode to Read Only.
+ if a.conf.ROMount || fmtStat == syscall.S_IFDIR {
+ mode = syscall.O_RDONLY
+ }
+
+ // Open the mount point & capture the FD.
+ f, err := fd.Open(a.prefix, openFlags|mode, 0)
+ if err != nil {
+ return nil, fmt.Errorf("unable to open file %q, err: %v", a.prefix, err)
+ }
+
+ // If the mount point has already been attached, close the FD.
+ a.attachedMu.Lock()
+ defer a.attachedMu.Unlock()
+ if a.attached {
+ f.Close()
+ return nil, fmt.Errorf("attach point already attached, prefix: %s", a.prefix)
+ }
+ a.attached = true
+
+ // Return a localFile object to the caller with the mount point FD
+ return newLocalFile(a, f, a.prefix, stat)
}
- a.attached = true
- return rv, nil
}
// makeQID returns a unique QID for the given stat buffer.
@@ -304,6 +333,8 @@ func getSupportedFileType(stat syscall.Stat_t) (fileType, error) {
ft = directory
case syscall.S_IFLNK:
ft = symlink
+ case syscall.S_IFSOCK:
+ ft = socket
default:
return unknown, syscall.EPERM
}
@@ -1026,7 +1057,7 @@ func (l *localFile) Flush() error {
// Connect implements p9.File.
func (l *localFile) Connect(p9.ConnectFlags) (*fd.FD, error) {
- return nil, syscall.ECONNREFUSED
+ return fd.OpenUnix(l.hostPath)
}
// Close implements p9.File.