From 13d36561b8a9cab6cf20b4b5053752955f451518 Mon Sep 17 00:00:00 2001 From: "Zyad A. Ali" Date: Fri, 30 Jul 2021 16:57:59 +0200 Subject: Return FDs in RegistryImpl functions and use Views. Update RegistryImpl functions to return file descriptions, instead of queues, and use Views in queue inodes. Updates #136 --- pkg/sentry/kernel/mq/mq.go | 64 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 5 deletions(-) (limited to 'pkg/sentry/kernel/mq/mq.go') diff --git a/pkg/sentry/kernel/mq/mq.go b/pkg/sentry/kernel/mq/mq.go index 954883c5f..217478dca 100644 --- a/pkg/sentry/kernel/mq/mq.go +++ b/pkg/sentry/kernel/mq/mq.go @@ -21,13 +21,16 @@ import ( "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/context" + "gvisor.dev/gvisor/pkg/errors/linuxerr" "gvisor.dev/gvisor/pkg/sentry/fs" + "gvisor.dev/gvisor/pkg/sentry/kernel/auth" "gvisor.dev/gvisor/pkg/sentry/vfs" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/waiter" ) const ( + MaxName = 255 // Maximum size for a queue name. maxPriority = linux.MQ_PRIO_MAX - 1 // Highest possible message priority. ) @@ -48,18 +51,20 @@ type Registry struct { // Registry to avoid dealing directly with the filesystem. RegistryImpl should // be implemented by mqfs and provided to Registry at initialization. type RegistryImpl interface { - // Lookup returns the queue with the given name, nil if non exists. - Lookup(context.Context, string) *Queue + // Get searchs for a queue with the given name, if it exists, the queue is + // used to create a new FD, return it and return true. If the queue doesn't + // exist, return false and no error. An error is returned if creation fails. + Get(ctx context.Context, name string, rOnly, wOnly, readWrite, block bool, flags uint32) (*vfs.FileDescription, bool, error) // New creates a new inode and file description using the given queue, - // inserts the inode into the filesystem tree with the given name, and + // inserts the inode into the filesystem tree using the given name, and // returns the file description. An error is returned if creation fails, or // if the name already exists. - New(context.Context, string, *Queue, linux.FileMode) (*vfs.FileDescription, error) + New(ctx context.Context, name string, q *Queue, rOnly, wOnly, readWrite, block bool, perm linux.FileMode, flags uint32) (*vfs.FileDescription, error) // Unlink removes the queue with given name from the registry, and returns // an error if the name doesn't exist. - Unlink(context.Context, string) error + Unlink(ctx context.Context, name string) error // Destroy destroys the registry. Destroy(context.Context) @@ -144,6 +149,43 @@ type View interface { waiter.Waitable } +// ReaderWriter provides a send and receive view into a queue. +type ReaderWriter struct { + *Queue + + block bool +} + +// Reader provides a send-only view into a queue. +type Reader struct { + *Queue + + block bool +} + +// Writer provides a receive-only view into a queue. +type Writer struct { + *Queue + + block bool +} + +// NewView creates a new view into a queue and returns it. +func NewView(q *Queue, rOnly, wOnly, readWrite, block bool) (View, error) { + switch { + case readWrite: + return ReaderWriter{Queue: q, block: block}, nil + case wOnly: + return Writer{Queue: q, block: block}, nil + case rOnly: + return Reader{Queue: q, block: block}, nil + default: + // This case can't happen, due to O_RDONLY flag being 0 and O_WRONLY + // being 1, so one of them must be true. + return nil, linuxerr.EINVAL + } +} + // Message holds a message exchanged through a Queue via mq_timedsend(2) and // mq_timedreceive(2), and additional info relating to the message. // @@ -243,3 +285,15 @@ func (q *Queue) EventUnregister(e *waiter.Entry) { q.senders.EventUnregister(e) q.receivers.EventUnregister(e) } + +// HasPermissions returns true if the given credentials meet the access +// permissions required by the queue. +func (q *Queue) HasPermissions(creds *auth.Credentials, req fs.PermMask) bool { + p := q.perms.Other + if q.owner.UID == creds.EffectiveKUID { + p = q.perms.User + } else if creds.InGroup(q.owner.GID) { + p = q.perms.Group + } + return p.SupersetOf(req) +} -- cgit v1.2.3