mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Move hostfs mount to Kernel struct.
This is needed to set up host fds passed through a Unix socket. Note that the host package depends on kernel, so we cannot set up the hostfs mount directly in Kernel.Init as we do for sockfs and pipefs. Also, adjust sockfs to make its setup look more like hostfs's and pipefs's. PiperOrigin-RevId: 308274053
This commit is contained in:
@@ -42,7 +42,7 @@ type filesystemType struct{}
|
||||
|
||||
// GetFilesystem implements FilesystemType.GetFilesystem.
|
||||
func (filesystemType) GetFilesystem(context.Context, *vfs.VirtualFilesystem, *auth.Credentials, string, vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) {
|
||||
panic("cannot instaniate a host filesystem")
|
||||
panic("host.filesystemType.GetFilesystem should never be called")
|
||||
}
|
||||
|
||||
// Name implements FilesystemType.Name.
|
||||
@@ -55,14 +55,14 @@ type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
}
|
||||
|
||||
// NewMount returns a new disconnected mount in vfsObj that may be passed to ImportFD.
|
||||
func NewMount(vfsObj *vfs.VirtualFilesystem) (*vfs.Mount, error) {
|
||||
// NewFilesystem sets up and returns a new hostfs filesystem.
|
||||
//
|
||||
// Note that there should only ever be one instance of host.filesystem,
|
||||
// a global mount for host fds.
|
||||
func NewFilesystem(vfsObj *vfs.VirtualFilesystem) *vfs.Filesystem {
|
||||
fs := &filesystem{}
|
||||
fs.Init(vfsObj, &filesystemType{})
|
||||
vfsfs := fs.VFSFilesystem()
|
||||
// NewDisconnectedMount will take an additional reference on vfsfs.
|
||||
defer vfsfs.DecRef()
|
||||
return vfsObj.NewDisconnectedMount(vfsfs, nil, &vfs.MountOptions{})
|
||||
fs.Init(vfsObj, filesystemType{})
|
||||
return fs.VFSFilesystem()
|
||||
}
|
||||
|
||||
// ImportFD sets up and returns a vfs.FileDescription from a donated fd.
|
||||
|
||||
@@ -24,26 +24,12 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
)
|
||||
|
||||
// NewFilesystem creates a new sockfs filesystem.
|
||||
//
|
||||
// Note that there should only ever be one instance of sockfs.Filesystem,
|
||||
// backing a global socket mount.
|
||||
func NewFilesystem(vfsObj *vfs.VirtualFilesystem) *vfs.Filesystem {
|
||||
fs, _, err := filesystemType{}.GetFilesystem(nil, vfsObj, nil, "", vfs.GetFilesystemOptions{})
|
||||
if err != nil {
|
||||
panic("failed to create sockfs filesystem")
|
||||
}
|
||||
return fs
|
||||
}
|
||||
|
||||
// filesystemType implements vfs.FilesystemType.
|
||||
type filesystemType struct{}
|
||||
|
||||
// GetFilesystem implements FilesystemType.GetFilesystem.
|
||||
func (fsType filesystemType) GetFilesystem(_ context.Context, vfsObj *vfs.VirtualFilesystem, _ *auth.Credentials, _ string, _ vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) {
|
||||
fs := &filesystem{}
|
||||
fs.Init(vfsObj, fsType)
|
||||
return fs.VFSFilesystem(), nil, nil
|
||||
panic("sockfs.filesystemType.GetFilesystem should never be called")
|
||||
}
|
||||
|
||||
// Name implements FilesystemType.Name.
|
||||
@@ -60,6 +46,16 @@ type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
}
|
||||
|
||||
// NewFilesystem sets up and returns a new sockfs filesystem.
|
||||
//
|
||||
// Note that there should only ever be one instance of sockfs.Filesystem,
|
||||
// backing a global socket mount.
|
||||
func NewFilesystem(vfsObj *vfs.VirtualFilesystem) *vfs.Filesystem {
|
||||
fs := &filesystem{}
|
||||
fs.Init(vfsObj, filesystemType{})
|
||||
return fs.VFSFilesystem()
|
||||
}
|
||||
|
||||
// inode implements kernfs.Inode.
|
||||
//
|
||||
// TODO(gvisor.dev/issue/1476): Add device numbers to this inode (which are
|
||||
|
||||
+31
-11
@@ -227,11 +227,6 @@ type Kernel struct {
|
||||
// by extMu.
|
||||
nextSocketEntry uint64
|
||||
|
||||
// socketMount is a disconnected vfs.Mount, not included in k.vfs,
|
||||
// representing a sockfs.filesystem. socketMount is used to back
|
||||
// VirtualDentries representing anonymous sockets.
|
||||
socketMount *vfs.Mount
|
||||
|
||||
// deviceRegistry is used to save/restore device.SimpleDevices.
|
||||
deviceRegistry struct{} `state:".(*device.Registry)"`
|
||||
|
||||
@@ -255,10 +250,22 @@ type Kernel struct {
|
||||
// VFS keeps the filesystem state used across the kernel.
|
||||
vfs vfs.VirtualFilesystem
|
||||
|
||||
// hostMount is the Mount used for file descriptors that were imported
|
||||
// from the host.
|
||||
hostMount *vfs.Mount
|
||||
|
||||
// pipeMount is the Mount used for pipes created by the pipe() and pipe2()
|
||||
// syscalls (as opposed to named pipes created by mknod()).
|
||||
pipeMount *vfs.Mount
|
||||
|
||||
// socketMount is the Mount used for sockets created by the socket() and
|
||||
// socketpair() syscalls. There are several cases where a socket dentry will
|
||||
// not be contained in socketMount:
|
||||
// 1. Socket files created by mknod()
|
||||
// 2. Socket fds imported from the host (Kernel.hostMount is used for these)
|
||||
// 3. Socket files created by binding Unix sockets to a file path
|
||||
socketMount *vfs.Mount
|
||||
|
||||
// If set to true, report address space activation waits as if the task is in
|
||||
// external wait so that the watchdog doesn't report the task stuck.
|
||||
SleepForAddressSpaceActivation bool
|
||||
@@ -377,7 +384,7 @@ func (k *Kernel) Init(args InitKernelArgs) error {
|
||||
defer socketFilesystem.DecRef()
|
||||
socketMount, err := k.vfs.NewDisconnectedMount(socketFilesystem, nil, &vfs.MountOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize socket mount: %v", err)
|
||||
return fmt.Errorf("failed to create sockfs mount: %v", err)
|
||||
}
|
||||
k.socketMount = socketMount
|
||||
}
|
||||
@@ -1526,11 +1533,6 @@ func (k *Kernel) ListSockets() []*SocketEntry {
|
||||
return socks
|
||||
}
|
||||
|
||||
// SocketMount returns the global socket mount.
|
||||
func (k *Kernel) SocketMount() *vfs.Mount {
|
||||
return k.socketMount
|
||||
}
|
||||
|
||||
// supervisorContext is a privileged context.
|
||||
type supervisorContext struct {
|
||||
context.NoopSleeper
|
||||
@@ -1629,7 +1631,25 @@ func (k *Kernel) VFS() *vfs.VirtualFilesystem {
|
||||
return &k.vfs
|
||||
}
|
||||
|
||||
// SetHostMount sets the hostfs mount.
|
||||
func (k *Kernel) SetHostMount(mnt *vfs.Mount) {
|
||||
if k.hostMount != nil {
|
||||
panic("Kernel.hostMount cannot be set more than once")
|
||||
}
|
||||
k.hostMount = mnt
|
||||
}
|
||||
|
||||
// HostMount returns the hostfs mount.
|
||||
func (k *Kernel) HostMount() *vfs.Mount {
|
||||
return k.hostMount
|
||||
}
|
||||
|
||||
// PipeMount returns the pipefs mount.
|
||||
func (k *Kernel) PipeMount() *vfs.Mount {
|
||||
return k.pipeMount
|
||||
}
|
||||
|
||||
// SocketMount returns the sockfs mount.
|
||||
func (k *Kernel) SocketMount() *vfs.Mount {
|
||||
return k.socketMount
|
||||
}
|
||||
|
||||
+1
-6
@@ -89,14 +89,9 @@ func createFDTableVFS2(ctx context.Context, console bool, stdioFDs []int) (*kern
|
||||
fdTable := k.NewFDTable()
|
||||
defer fdTable.DecRef()
|
||||
|
||||
hostMount, err := vfshost.NewMount(k.VFS())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating host mount: %w", err)
|
||||
}
|
||||
|
||||
for appFD, hostFD := range stdioFDs {
|
||||
// TODO(gvisor.dev/issue/1482): Add TTY support.
|
||||
appFile, err := vfshost.ImportFD(hostMount, hostFD, false)
|
||||
appFile, err := vfshost.ImportFD(k.HostMount(), hostFD, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/host"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/user"
|
||||
vfs2host "gvisor.dev/gvisor/pkg/sentry/fsimpl/host"
|
||||
"gvisor.dev/gvisor/pkg/sentry/inet"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
@@ -46,6 +47,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/syscalls/linux/vfs2"
|
||||
"gvisor.dev/gvisor/pkg/sentry/time"
|
||||
"gvisor.dev/gvisor/pkg/sentry/usage"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/watchdog"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
@@ -329,6 +331,17 @@ func New(args Args) (*Loader, error) {
|
||||
return nil, fmt.Errorf("creating pod mount hints: %v", err)
|
||||
}
|
||||
|
||||
if kernel.VFS2Enabled {
|
||||
// Set up host mount that will be used for imported fds.
|
||||
hostFilesystem := vfs2host.NewFilesystem(k.VFS())
|
||||
defer hostFilesystem.DecRef()
|
||||
hostMount, err := k.VFS().NewDisconnectedMount(hostFilesystem, nil, &vfs.MountOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create hostfs mount: %v", err)
|
||||
}
|
||||
k.SetHostMount(hostMount)
|
||||
}
|
||||
|
||||
// Make host FDs stable between invocations. Host FDs must map to the exact
|
||||
// same number when the sandbox is restored. Otherwise the wrong FD will be
|
||||
// used.
|
||||
|
||||
Reference in New Issue
Block a user