summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/kernel/mq/mq.go
diff options
context:
space:
mode:
authorZyad A. Ali <zyad.ali.me@gmail.com>2021-07-30 16:57:59 +0200
committerZyad A. Ali <zyad.ali.me@gmail.com>2021-09-28 20:43:52 +0200
commit13d36561b8a9cab6cf20b4b5053752955f451518 (patch)
treef2be0923e303b147beb251b4b77be8a66e52605d /pkg/sentry/kernel/mq/mq.go
parent7508a0efeeef19a3e08e06e80be8258743438412 (diff)
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
Diffstat (limited to 'pkg/sentry/kernel/mq/mq.go')
-rw-r--r--pkg/sentry/kernel/mq/mq.go64
1 files changed, 59 insertions, 5 deletions
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)
+}