summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJamie Liu <jamieliu@google.com>2020-01-24 12:53:29 -0800
committergVisor bot <gvisor-bot@google.com>2020-01-24 12:54:39 -0800
commitd135b5abf6eafa92d2745dc98d48ef39d2f90e75 (patch)
tree6508a91a64e0b07739c31ed366c59e988cfc79d7
parentfb80979e3fe2614414d2d23c27e41bdb9e7c8541 (diff)
Add anonymous device number allocation to VFS2.
Note that in VFS2, filesystem device numbers are per-vfs.FilesystemImpl rather than global, avoiding the need for a "registry" type to handle save/restore. (This is more consistent with Linux anyway: compare e.g. mm/shmem.c:shmem_mount() => fs/super.c:mount_nodev() => (indirectly) set_anon_super().) PiperOrigin-RevId: 291425193
-rw-r--r--pkg/sentry/vfs/device.go29
-rw-r--r--pkg/sentry/vfs/vfs.go18
2 files changed, 43 insertions, 4 deletions
diff --git a/pkg/sentry/vfs/device.go b/pkg/sentry/vfs/device.go
index cb672e36f..9f9d6e783 100644
--- a/pkg/sentry/vfs/device.go
+++ b/pkg/sentry/vfs/device.go
@@ -98,3 +98,32 @@ func (vfs *VirtualFilesystem) OpenDeviceSpecialFile(ctx context.Context, mnt *Mo
}
return rd.dev.Open(ctx, mnt, d, *opts)
}
+
+// GetAnonBlockDevMinor allocates and returns an unused minor device number for
+// an "anonymous" block device with major number 0.
+func (vfs *VirtualFilesystem) GetAnonBlockDevMinor() (uint32, error) {
+ vfs.anonBlockDevMinorMu.Lock()
+ defer vfs.anonBlockDevMinorMu.Unlock()
+ minor := vfs.anonBlockDevMinorNext
+ const maxDevMinor = (1 << 20) - 1
+ for minor < maxDevMinor {
+ if _, ok := vfs.anonBlockDevMinor[minor]; !ok {
+ vfs.anonBlockDevMinor[minor] = struct{}{}
+ vfs.anonBlockDevMinorNext = minor + 1
+ return minor, nil
+ }
+ minor++
+ }
+ return 0, syserror.EMFILE
+}
+
+// PutAnonBlockDevMinor deallocates a minor device number returned by a
+// previous call to GetAnonBlockDevMinor.
+func (vfs *VirtualFilesystem) PutAnonBlockDevMinor(minor uint32) {
+ vfs.anonBlockDevMinorMu.Lock()
+ defer vfs.anonBlockDevMinorMu.Unlock()
+ delete(vfs.anonBlockDevMinor, minor)
+ if minor < vfs.anonBlockDevMinorNext {
+ vfs.anonBlockDevMinorNext = minor
+ }
+}
diff --git a/pkg/sentry/vfs/vfs.go b/pkg/sentry/vfs/vfs.go
index 1f21b0b31..1f6f56293 100644
--- a/pkg/sentry/vfs/vfs.go
+++ b/pkg/sentry/vfs/vfs.go
@@ -80,6 +80,14 @@ type VirtualFilesystem struct {
devicesMu sync.RWMutex
devices map[devTuple]*registeredDevice
+ // anonBlockDevMinor contains all allocated anonymous block device minor
+ // numbers. anonBlockDevMinorNext is a lower bound for the smallest
+ // unallocated anonymous block device number. anonBlockDevMinorNext and
+ // anonBlockDevMinor are protected by anonBlockDevMinorMu.
+ anonBlockDevMinorMu sync.Mutex
+ anonBlockDevMinorNext uint32
+ anonBlockDevMinor map[uint32]struct{}
+
// fsTypes contains all registered FilesystemTypes. fsTypes is protected by
// fsTypesMu.
fsTypesMu sync.RWMutex
@@ -94,10 +102,12 @@ type VirtualFilesystem struct {
// New returns a new VirtualFilesystem with no mounts or FilesystemTypes.
func New() *VirtualFilesystem {
vfs := &VirtualFilesystem{
- mountpoints: make(map[*Dentry]map[*Mount]struct{}),
- devices: make(map[devTuple]*registeredDevice),
- fsTypes: make(map[string]*registeredFilesystemType),
- filesystems: make(map[*Filesystem]struct{}),
+ mountpoints: make(map[*Dentry]map[*Mount]struct{}),
+ devices: make(map[devTuple]*registeredDevice),
+ anonBlockDevMinorNext: 1,
+ anonBlockDevMinor: make(map[uint32]struct{}),
+ fsTypes: make(map[string]*registeredFilesystemType),
+ filesystems: make(map[*Filesystem]struct{}),
}
vfs.mounts.Init()
return vfs