summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/fsimpl/mqfs/BUILD1
-rw-r--r--pkg/sentry/fsimpl/mqfs/mqfs.go61
-rw-r--r--pkg/sentry/fsimpl/mqfs/registry.go34
-rw-r--r--pkg/sentry/kernel/BUILD1
-rw-r--r--pkg/sentry/kernel/ipc_namespace.go21
-rw-r--r--pkg/sentry/kernel/mq/mq.go5
6 files changed, 96 insertions, 27 deletions
diff --git a/pkg/sentry/fsimpl/mqfs/BUILD b/pkg/sentry/fsimpl/mqfs/BUILD
index 6892c6c25..e688b9b48 100644
--- a/pkg/sentry/fsimpl/mqfs/BUILD
+++ b/pkg/sentry/fsimpl/mqfs/BUILD
@@ -31,6 +31,7 @@ go_library(
"//pkg/refsvfs2",
"//pkg/sentry/fsimpl/kernfs",
"//pkg/sentry/kernel/auth",
+ "//pkg/sentry/kernel/ipc",
"//pkg/sentry/kernel/mq",
"//pkg/sentry/vfs",
"//pkg/sync",
diff --git a/pkg/sentry/fsimpl/mqfs/mqfs.go b/pkg/sentry/fsimpl/mqfs/mqfs.go
index a92012deb..ed559cd13 100644
--- a/pkg/sentry/fsimpl/mqfs/mqfs.go
+++ b/pkg/sentry/fsimpl/mqfs/mqfs.go
@@ -24,6 +24,8 @@ import (
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
+ "gvisor.dev/gvisor/pkg/sentry/kernel/ipc"
+ "gvisor.dev/gvisor/pkg/sentry/kernel/mq"
"gvisor.dev/gvisor/pkg/sentry/vfs"
)
@@ -47,28 +49,32 @@ func (FilesystemType) Release(ctx context.Context) {}
// GetFilesystem implements vfs.FilesystemType.GetFilesystem.
func (ft FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials, source string, opts vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) {
- devMinor, err := vfsObj.GetAnonBlockDevMinor()
- if err != nil {
- return nil, nil, err
+ // mqfs is initialized only once per ipc namespace. Each ipc namespace has
+ // a POSIX message registry with a root dentry, filesystem, and a
+ // disconnected mount. We want the fs to be consistent for all processes in
+ // the same ipc namespace, so instead of creating a new fs and root dentry,
+ // we retreive them using IPCNamespace.PosixQueues and use them.
+
+ i := ipcNamespaceFromContext(ctx)
+ if i == nil {
+ return nil, nil, fmt.Errorf("mqfs.FilesystemType.GetFilesystem: ipc namespace doesn't exist")
+ }
+ defer i.DecRef(ctx)
+
+ registry := i.PosixQueues()
+ if registry == nil {
+ return nil, nil, fmt.Errorf("mqfs.FilesystemType.GetFilesystem: ipc namespace doesn't have a POSIX registry")
}
+ impl := registry.Impl().(*RegistryImpl)
maxCachedDentries, err := maxCachedDentries(ctx, vfs.GenericParseMountOptions(opts.Data))
if err != nil {
return nil, nil, err
}
+ impl.fs.MaxCachedDentries = maxCachedDentries
- fs := &filesystem{
- devMinor: devMinor,
- Filesystem: kernfs.Filesystem{
- MaxCachedDentries: maxCachedDentries,
- },
- }
- fs.VFSFilesystem().Init(vfsObj, &ft, fs)
-
- var dentry kernfs.Dentry
- dentry.InitRoot(&fs.Filesystem, fs.newRootInode(ctx, creds))
-
- return fs.VFSFilesystem(), dentry.VFSDentry(), nil
+ impl.root.IncRef()
+ return impl.fs.VFSFilesystem(), impl.root.VFSDentry(), nil
}
// maxCachedDentries checks mopts for dentry_cache_limit. If a value is
@@ -93,15 +99,40 @@ func maxCachedDentries(ctx context.Context, mopts map[string]string) (_ uint64,
type filesystem struct {
kernfs.Filesystem
devMinor uint32
+
+ // root is the filesystem's root dentry. Since we take a reference on it in
+ // GetFilesystem, we should release it when the fs is released.
+ root *kernfs.Dentry
}
// Release implements vfs.FilesystemImpl.Release.
func (fs *filesystem) Release(ctx context.Context) {
fs.Filesystem.VFSFilesystem().VirtualFilesystem().PutAnonBlockDevMinor(fs.devMinor)
fs.Filesystem.Release(ctx)
+ fs.root.DecRef(ctx)
}
// MountOptions implements vfs.FilesystemImpl.MountOptions.
func (fs *filesystem) MountOptions() string {
return fmt.Sprintf("dentry_cache_limit=%d", fs.MaxCachedDentries)
}
+
+// ipcNamespace defines functions we need from kernel.IPCNamespace. We redefine
+// ipcNamespace along with ipcNamespaceFromContext to avoid circular dependency
+// with package sentry/kernel.
+type ipcNamespace interface {
+ // PosixQueues returns a POSIX message queue registry.
+ PosixQueues() *mq.Registry
+
+ // DecRef decrements ipcNamespace's number of references.
+ DecRef(ctx context.Context)
+}
+
+// ipcNamespaceFromContext returns the IPC namespace in which ctx is executing.
+// Copied from package sentry/kernel.
+func ipcNamespaceFromContext(ctx context.Context) ipcNamespace {
+ if v := ctx.Value(ipc.CtxIPCNamespace); v != nil {
+ return v.(ipcNamespace)
+ }
+ return nil
+}
diff --git a/pkg/sentry/fsimpl/mqfs/registry.go b/pkg/sentry/fsimpl/mqfs/registry.go
index 3875b39ee..9361b7eb4 100644
--- a/pkg/sentry/fsimpl/mqfs/registry.go
+++ b/pkg/sentry/fsimpl/mqfs/registry.go
@@ -50,12 +50,32 @@ type RegistryImpl struct {
// NewRegistryImpl returns a new, initialized RegistryImpl, and takes a
// reference on root.
-func NewRegistryImpl(root *kernfs.Dentry, fs *filesystem) *RegistryImpl {
- root.IncRef()
- return &RegistryImpl{
- root: root,
- fs: fs,
+func NewRegistryImpl(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials) (*RegistryImpl, error) {
+ devMinor, err := vfsObj.GetAnonBlockDevMinor()
+ if err != nil {
+ return nil, err
+ }
+
+ var dentry kernfs.Dentry
+ fs := &filesystem{
+ devMinor: devMinor,
+ root: &dentry,
+ }
+ fs.VFSFilesystem().Init(vfsObj, &FilesystemType{}, fs)
+
+ dentry.InitRoot(&fs.Filesystem, fs.newRootInode(ctx, creds))
+ dentry.IncRef()
+
+ mount, err := vfsObj.NewDisconnectedMount(fs.VFSFilesystem(), dentry.VFSDentry(), &vfs.MountOptions{})
+ if err != nil {
+ return nil, err
}
+
+ return &RegistryImpl{
+ root: &dentry,
+ fs: fs,
+ mount: mount,
+ }, nil
}
// Lookup implements mq.RegistryImpl.Lookup.
@@ -83,11 +103,11 @@ func (r *RegistryImpl) New(ctx context.Context, name string, q *mq.Queue, perm l
}
fd := &queueFD{queue: q}
- err = fd.Init(r.mount, r.root, qInode.data, &qInode.locks, 0 /* flags */)
+ err = fd.Init(r.mount, r.root, q, qInode.Locks(), 0 /* flags */)
if err != nil {
return nil, err
}
- return fd.VFSFileDescription(), nil
+ return &fd.vfsfd, nil
}
// Unlink implements mq.RegistryImpl.Unlink.
diff --git a/pkg/sentry/kernel/BUILD b/pkg/sentry/kernel/BUILD
index 6ff3deb97..9f30a7706 100644
--- a/pkg/sentry/kernel/BUILD
+++ b/pkg/sentry/kernel/BUILD
@@ -249,6 +249,7 @@ go_library(
"//pkg/sentry/fs/timerfd",
"//pkg/sentry/fsbridge",
"//pkg/sentry/fsimpl/kernfs",
+ "//pkg/sentry/fsimpl/mqfs",
"//pkg/sentry/fsimpl/pipefs",
"//pkg/sentry/fsimpl/sockfs",
"//pkg/sentry/fsimpl/timerfd",
diff --git a/pkg/sentry/kernel/ipc_namespace.go b/pkg/sentry/kernel/ipc_namespace.go
index aa9c3fb31..11b4545c6 100644
--- a/pkg/sentry/kernel/ipc_namespace.go
+++ b/pkg/sentry/kernel/ipc_namespace.go
@@ -15,12 +15,16 @@
package kernel
import (
+ "fmt"
+
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/sentry/fsimpl/mqfs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/kernel/mq"
"gvisor.dev/gvisor/pkg/sentry/kernel/msgqueue"
"gvisor.dev/gvisor/pkg/sentry/kernel/semaphore"
"gvisor.dev/gvisor/pkg/sentry/kernel/shm"
+ "gvisor.dev/gvisor/pkg/sentry/vfs"
)
// IPCNamespace represents an IPC namespace.
@@ -72,12 +76,19 @@ func (i *IPCNamespace) ShmRegistry() *shm.Registry {
return i.shms
}
-// SetPosixQueues sets value of posixQueues if the value is currently nil,
-// otherwise returns without doing anything.
-func (i *IPCNamespace) SetPosixQueues(r *mq.Registry) {
- if i.posixQueues == nil {
- i.posixQueues = r
+// InitPosixQueues creates a new POSIX queue registry, and returns an error if
+// the registry was previously initialized.
+func (i *IPCNamespace) InitPosixQueues(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials) error {
+ if i.posixQueues != nil {
+ return fmt.Errorf("IPCNamespace.InitPosixQueues: already initialized")
+ }
+
+ impl, err := mqfs.NewRegistryImpl(ctx, vfsObj, creds)
+ if err != nil {
+ return err
}
+ i.posixQueues = mq.NewRegistry(impl)
+ return nil
}
// PosixQueues returns the posix message queue registry for this namespace.
diff --git a/pkg/sentry/kernel/mq/mq.go b/pkg/sentry/kernel/mq/mq.go
index be46f78c8..739ea2f1c 100644
--- a/pkg/sentry/kernel/mq/mq.go
+++ b/pkg/sentry/kernel/mq/mq.go
@@ -79,6 +79,11 @@ func (r *Registry) Destroy(ctx context.Context) {
r.impl.Destroy(ctx)
}
+// Impl returns RegistryImpl inside r.
+func (r *Registry) Impl() RegistryImpl {
+ return r.impl
+}
+
// Queue represents a POSIX message queue.
//
// +stateify savable