mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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).
This commit is contained in:
@@ -22,6 +22,7 @@ import (
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"net"
|
||||
)
|
||||
|
||||
// ReadWriter implements io.ReadWriter, io.ReaderAt, and io.WriterAt for fd. It
|
||||
@@ -185,6 +186,21 @@ func OpenAt(dir *FD, path string, flags int, mode uint32) (*FD, error) {
|
||||
return New(f), nil
|
||||
}
|
||||
|
||||
// OpenUnix TODO: DOC
|
||||
func OpenUnix(path string) (*FD, error) {
|
||||
addr, _ := net.ResolveUnixAddr("unix", path)
|
||||
f, err := net.DialUnix("unix", nil, addr); if err != nil {
|
||||
return nil, fmt.Errorf("unable to open socket: %q, err: %v", path, err)
|
||||
}
|
||||
fConnd, err := f.File(); if err != nil {
|
||||
return nil, fmt.Errorf("unable to convert to os.File: %q, err: %v", path, err)
|
||||
}
|
||||
fdConnd, err := NewFromFile(fConnd); if err != nil {
|
||||
return nil, fmt.Errorf("unable to convert os.File to fd.FD: %q, err: %v", path, err)
|
||||
}
|
||||
return fdConnd, nil
|
||||
}
|
||||
|
||||
// Close closes the file descriptor contained in the FD.
|
||||
//
|
||||
// Close is safe to call multiple times, but will return an error after the
|
||||
|
||||
@@ -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: {},
|
||||
|
||||
+52
-21
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user