summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/fs')
-rw-r--r--pkg/sentry/fs/ashmem/BUILD65
-rw-r--r--pkg/sentry/fs/ashmem/area.go308
-rw-r--r--pkg/sentry/fs/ashmem/device.go61
-rw-r--r--pkg/sentry/fs/ashmem/pin_board.go127
-rw-r--r--pkg/sentry/fs/ashmem/pin_board_test.go130
-rw-r--r--pkg/sentry/fs/binder/BUILD27
-rw-r--r--pkg/sentry/fs/binder/binder.go260
-rw-r--r--pkg/sentry/fs/dev/BUILD2
-rw-r--r--pkg/sentry/fs/dev/dev.go14
-rw-r--r--pkg/sentry/fs/dev/fs.go37
10 files changed, 2 insertions, 1029 deletions
diff --git a/pkg/sentry/fs/ashmem/BUILD b/pkg/sentry/fs/ashmem/BUILD
deleted file mode 100644
index 5b755cec5..000000000
--- a/pkg/sentry/fs/ashmem/BUILD
+++ /dev/null
@@ -1,65 +0,0 @@
-package(licenses = ["notice"])
-
-load("//tools/go_stateify:defs.bzl", "go_library", "go_test")
-load("//tools/go_generics:defs.bzl", "go_template_instance")
-
-go_library(
- name = "ashmem",
- srcs = [
- "area.go",
- "device.go",
- "pin_board.go",
- "uint64_range.go",
- "uint64_set.go",
- ],
- importpath = "gvisor.dev/gvisor/pkg/sentry/fs/ashmem",
- visibility = ["//pkg/sentry:internal"],
- deps = [
- "//pkg/abi/linux",
- "//pkg/sentry/arch",
- "//pkg/sentry/context",
- "//pkg/sentry/fs",
- "//pkg/sentry/fs/fsutil",
- "//pkg/sentry/fs/tmpfs",
- "//pkg/sentry/kernel/time",
- "//pkg/sentry/memmap",
- "//pkg/sentry/usage",
- "//pkg/sentry/usermem",
- "//pkg/syserror",
- "//pkg/waiter",
- ],
-)
-
-go_test(
- name = "ashmem_test",
- size = "small",
- srcs = ["pin_board_test.go"],
- embed = [":ashmem"],
- deps = [
- "//pkg/abi/linux",
- "//pkg/sentry/usermem",
- ],
-)
-
-go_template_instance(
- name = "uint64_range",
- out = "uint64_range.go",
- package = "ashmem",
- template = "//pkg/segment:generic_range",
- types = {
- "T": "uint64",
- },
-)
-
-go_template_instance(
- name = "uint64_set",
- out = "uint64_set.go",
- package = "ashmem",
- template = "//pkg/segment:generic_set",
- types = {
- "Key": "uint64",
- "Range": "Range",
- "Value": "noValue",
- "Functions": "setFunctions",
- },
-)
diff --git a/pkg/sentry/fs/ashmem/area.go b/pkg/sentry/fs/ashmem/area.go
deleted file mode 100644
index 3b8d6ca89..000000000
--- a/pkg/sentry/fs/ashmem/area.go
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package ashmem
-
-import (
- "sync"
-
- "gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/arch"
- "gvisor.dev/gvisor/pkg/sentry/context"
- "gvisor.dev/gvisor/pkg/sentry/fs"
- "gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
- "gvisor.dev/gvisor/pkg/sentry/fs/tmpfs"
- "gvisor.dev/gvisor/pkg/sentry/memmap"
- "gvisor.dev/gvisor/pkg/sentry/usage"
- "gvisor.dev/gvisor/pkg/sentry/usermem"
- "gvisor.dev/gvisor/pkg/syserror"
- "gvisor.dev/gvisor/pkg/waiter"
-)
-
-const (
- // namePrefix is the name prefix assumed and forced by the Linux implementation.
- namePrefix = "dev/ashmem"
-
- // nameLen is the maximum name length.
- nameLen = 256
-)
-
-// Area implements fs.FileOperations.
-//
-// +stateify savable
-type Area struct {
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoSplice `state:"nosave"`
- fsutil.FileNoopFlush `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileUseInodeUnstableAttr `state:"nosave"`
- waiter.AlwaysReady `state:"nosave"`
-
- ad *Device
-
- // mu protects fields below.
- mu sync.Mutex `state:"nosave"`
- tmpfsFile *fs.File
- name string
- size uint64
- perms usermem.AccessType
- pb *PinBoard
-}
-
-// Release implements fs.FileOperations.Release.
-func (a *Area) Release() {
- a.mu.Lock()
- defer a.mu.Unlock()
- if a.tmpfsFile != nil {
- a.tmpfsFile.DecRef()
- a.tmpfsFile = nil
- }
-}
-
-// Seek implements fs.FileOperations.Seek.
-func (a *Area) Seek(ctx context.Context, file *fs.File, whence fs.SeekWhence, offset int64) (int64, error) {
- a.mu.Lock()
- defer a.mu.Unlock()
- if a.size == 0 {
- return 0, syserror.EINVAL
- }
- if a.tmpfsFile == nil {
- return 0, syserror.EBADF
- }
- return a.tmpfsFile.FileOperations.Seek(ctx, file, whence, offset)
-}
-
-// Read implements fs.FileOperations.Read.
-func (a *Area) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
- a.mu.Lock()
- defer a.mu.Unlock()
- if a.size == 0 {
- return 0, nil
- }
- if a.tmpfsFile == nil {
- return 0, syserror.EBADF
- }
- return a.tmpfsFile.FileOperations.Read(ctx, file, dst, offset)
-}
-
-// Write implements fs.FileOperations.Write.
-func (a *Area) Write(ctx context.Context, file *fs.File, src usermem.IOSequence, offset int64) (int64, error) {
- return 0, syserror.ENOSYS
-}
-
-// ConfigureMMap implements fs.FileOperations.ConfigureMMap.
-func (a *Area) ConfigureMMap(ctx context.Context, file *fs.File, opts *memmap.MMapOpts) error {
- a.mu.Lock()
- defer a.mu.Unlock()
- if a.size == 0 {
- return syserror.EINVAL
- }
-
- if !a.perms.SupersetOf(opts.Perms) {
- return syserror.EPERM
- }
- opts.MaxPerms = opts.MaxPerms.Intersect(a.perms)
-
- if a.tmpfsFile == nil {
- tmpfsInodeOps := tmpfs.NewInMemoryFile(ctx, usage.Tmpfs, fs.UnstableAttr{})
- tmpfsInode := fs.NewInode(ctx, tmpfsInodeOps, fs.NewPseudoMountSource(ctx), fs.StableAttr{})
- dirent := fs.NewDirent(ctx, tmpfsInode, namePrefix+"/"+a.name)
- tmpfsFile, err := tmpfsInode.GetFile(ctx, dirent, fs.FileFlags{Read: true, Write: true})
- // Drop the extra reference on the Dirent.
- dirent.DecRef()
-
- if err != nil {
- return err
- }
-
- // Truncate to the size set by ASHMEM_SET_SIZE ioctl.
- err = tmpfsInodeOps.Truncate(ctx, tmpfsInode, int64(a.size))
- if err != nil {
- return err
- }
- a.tmpfsFile = tmpfsFile
- a.pb = NewPinBoard()
- }
-
- return a.tmpfsFile.ConfigureMMap(ctx, opts)
-}
-
-// Ioctl implements fs.FileOperations.Ioctl.
-func (a *Area) Ioctl(ctx context.Context, _ *fs.File, io usermem.IO, args arch.SyscallArguments) (uintptr, error) {
- // Switch on ioctl request.
- switch args[1].Uint() {
- case linux.AshmemSetNameIoctl:
- name, err := usermem.CopyStringIn(ctx, io, args[2].Pointer(), nameLen-1, usermem.IOOpts{
- AddressSpaceActive: true,
- })
- if err != nil {
- return 0, err
- }
-
- a.mu.Lock()
- defer a.mu.Unlock()
-
- // Cannot set name for already mapped ashmem.
- if a.tmpfsFile != nil {
- return 0, syserror.EINVAL
- }
- a.name = name
- return 0, nil
-
- case linux.AshmemGetNameIoctl:
- a.mu.Lock()
- var local []byte
- if a.name != "" {
- nameLen := len([]byte(a.name))
- local = make([]byte, nameLen, nameLen+1)
- copy(local, []byte(a.name))
- local = append(local, 0)
- } else {
- nameLen := len([]byte(namePrefix))
- local = make([]byte, nameLen, nameLen+1)
- copy(local, []byte(namePrefix))
- local = append(local, 0)
- }
- a.mu.Unlock()
-
- if _, err := io.CopyOut(ctx, args[2].Pointer(), local, usermem.IOOpts{
- AddressSpaceActive: true,
- }); err != nil {
- return 0, syserror.EFAULT
- }
- return 0, nil
-
- case linux.AshmemSetSizeIoctl:
- a.mu.Lock()
- defer a.mu.Unlock()
-
- // Cannot set size for already mapped ashmem.
- if a.tmpfsFile != nil {
- return 0, syserror.EINVAL
- }
- a.size = uint64(args[2].SizeT())
- return 0, nil
-
- case linux.AshmemGetSizeIoctl:
- return uintptr(a.size), nil
-
- case linux.AshmemPinIoctl, linux.AshmemUnpinIoctl, linux.AshmemGetPinStatusIoctl:
- // Locking and unlocking is ok since once tmpfsFile is set, it won't be nil again
- // even after unmapping! Unlocking is needed in order to avoid a deadlock on
- // usermem.CopyObjectIn.
-
- // Cannot execute pin-related ioctls before mapping.
- a.mu.Lock()
- if a.tmpfsFile == nil {
- a.mu.Unlock()
- return 0, syserror.EINVAL
- }
- a.mu.Unlock()
-
- var pin linux.AshmemPin
- _, err := usermem.CopyObjectIn(ctx, io, args[2].Pointer(), &pin, usermem.IOOpts{
- AddressSpaceActive: true,
- })
- if err != nil {
- return 0, syserror.EFAULT
- }
-
- a.mu.Lock()
- defer a.mu.Unlock()
- return a.pinOperation(pin, args[1].Uint())
-
- case linux.AshmemPurgeAllCachesIoctl:
- return 0, nil
-
- case linux.AshmemSetProtMaskIoctl:
- prot := uint64(args[2].ModeT())
- perms := usermem.AccessType{
- Read: prot&linux.PROT_READ != 0,
- Write: prot&linux.PROT_WRITE != 0,
- Execute: prot&linux.PROT_EXEC != 0,
- }
-
- a.mu.Lock()
- defer a.mu.Unlock()
-
- // Can only narrow prot mask.
- if !a.perms.SupersetOf(perms) {
- return 0, syserror.EINVAL
- }
-
- // TODO(b/30946773,gvisor.dev/issue/153): If personality flag
- // READ_IMPLIES_EXEC is set, set PROT_EXEC if PORT_READ is set.
-
- a.perms = perms
- return 0, nil
-
- case linux.AshmemGetProtMaskIoctl:
- return uintptr(a.perms.Prot()), nil
- default:
- // Ioctls irrelevant to Ashmem.
- return 0, syserror.EINVAL
- }
-}
-
-// pinOperation should only be called while holding a.mu.
-func (a *Area) pinOperation(pin linux.AshmemPin, op uint32) (uintptr, error) {
- // Page-align a.size for checks.
- pageAlignedSize, ok := usermem.Addr(a.size).RoundUp()
- if !ok {
- return 0, syserror.EINVAL
- }
- // Len 0 means everything onward.
- if pin.Len == 0 {
- pin.Len = uint32(pageAlignedSize) - pin.Offset
- }
- // Both Offset and Len have to be page-aligned.
- if pin.Offset%uint32(usermem.PageSize) != 0 {
- return 0, syserror.EINVAL
- }
- if pin.Len%uint32(usermem.PageSize) != 0 {
- return 0, syserror.EINVAL
- }
- // Adding Offset and Len must not cause an uint32 overflow.
- if end := pin.Offset + pin.Len; end < pin.Offset {
- return 0, syserror.EINVAL
- }
- // Pin range must not exceed a's size.
- if uint32(pageAlignedSize) < pin.Offset+pin.Len {
- return 0, syserror.EINVAL
- }
- // Handle each operation.
- r := RangeFromAshmemPin(pin)
- switch op {
- case linux.AshmemPinIoctl:
- if a.pb.PinRange(r) {
- return linux.AshmemWasPurged, nil
- }
- return linux.AshmemNotPurged, nil
-
- case linux.AshmemUnpinIoctl:
- // TODO(b/30946773): Implement purge on unpin.
- a.pb.UnpinRange(r)
- return 0, nil
-
- case linux.AshmemGetPinStatusIoctl:
- if a.pb.RangePinnedStatus(r) {
- return linux.AshmemIsPinned, nil
- }
- return linux.AshmemIsUnpinned, nil
-
- default:
- panic("unreachable")
- }
-
-}
diff --git a/pkg/sentry/fs/ashmem/device.go b/pkg/sentry/fs/ashmem/device.go
deleted file mode 100644
index 776f54abe..000000000
--- a/pkg/sentry/fs/ashmem/device.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package ashmem implements Android ashmem module (Anonymus Shared Memory).
-package ashmem
-
-import (
- "gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/context"
- "gvisor.dev/gvisor/pkg/sentry/fs"
- "gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
- "gvisor.dev/gvisor/pkg/sentry/usermem"
-)
-
-// Device implements fs.InodeOperations.
-//
-// +stateify savable
-type Device struct {
- fsutil.InodeGenericChecker `state:"nosave"`
- fsutil.InodeNoExtendedAttributes `state:"nosave"`
- fsutil.InodeNoopAllocate `state:"nosave"`
- fsutil.InodeNoopRelease `state:"nosave"`
- fsutil.InodeNoopTruncate `state:"nosave"`
- fsutil.InodeNoopWriteOut `state:"nosave"`
- fsutil.InodeNotDirectory `state:"nosave"`
- fsutil.InodeNotMappable `state:"nosave"`
- fsutil.InodeNotSocket `state:"nosave"`
- fsutil.InodeNotSymlink `state:"nosave"`
- fsutil.InodeVirtual `state:"nosave"`
-
- fsutil.InodeSimpleAttributes
-}
-
-var _ fs.InodeOperations = (*Device)(nil)
-
-// NewDevice creates and initializes a Device structure.
-func NewDevice(ctx context.Context, owner fs.FileOwner, fp fs.FilePermissions) *Device {
- return &Device{
- InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fp, linux.ANON_INODE_FS_MAGIC),
- }
-}
-
-// GetFile implements fs.InodeOperations.GetFile.
-func (ad *Device) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
- return fs.NewFile(ctx, d, flags, &Area{
- ad: ad,
- tmpfsFile: nil,
- perms: usermem.AnyAccess,
- }), nil
-}
diff --git a/pkg/sentry/fs/ashmem/pin_board.go b/pkg/sentry/fs/ashmem/pin_board.go
deleted file mode 100644
index c5400dd94..000000000
--- a/pkg/sentry/fs/ashmem/pin_board.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package ashmem
-
-import "gvisor.dev/gvisor/pkg/abi/linux"
-
-const maxUint64 = ^uint64(0)
-
-// setFunctions implements segment.Functions generated from segment.Functions for
-// uint64 Key and noValue Value. For more information, see the build file and
-// segment set implementation at pkg/segment/set.go.
-type setFunctions struct{}
-
-// noValue is a type of range attached value, which is irrelevant here.
-type noValue struct{}
-
-// MinKey implements segment.Functions.MinKey.
-func (setFunctions) MinKey() uint64 {
- return 0
-}
-
-// MaxKey implements segment.Functions.MaxKey.
-func (setFunctions) MaxKey() uint64 {
- return maxUint64
-}
-
-// ClearValue implements segment.Functions.ClearValue.
-func (setFunctions) ClearValue(*noValue) {
- return
-}
-
-// Merge implements segment.Functions.Merge.
-func (setFunctions) Merge(Range, noValue, Range, noValue) (noValue, bool) {
- return noValue{}, true
-}
-
-// Split implements segment.Functions.Split.
-func (setFunctions) Split(Range, noValue, uint64) (noValue, noValue) {
- return noValue{}, noValue{}
-}
-
-// PinBoard represents a set of pinned ranges in ashmem.
-//
-// segment.Set is used for implementation where segments represent
-// ranges of pinned bytes, while gaps represent ranges of unpinned
-// bytes. All ranges are page-aligned.
-//
-// +stateify savable
-type PinBoard struct {
- Set
-}
-
-// NewPinBoard creates a new pin board with all pages pinned.
-func NewPinBoard() *PinBoard {
- var pb PinBoard
- pb.PinRange(Range{0, maxUint64})
- return &pb
-}
-
-// PinRange pins all pages in the specified range and returns true
-// if there are any newly pinned pages.
-func (pb *PinBoard) PinRange(r Range) bool {
- pinnedPages := false
- for gap := pb.LowerBoundGap(r.Start); gap.Ok() && gap.Start() < r.End; {
- common := gap.Range().Intersect(r)
- if common.Length() == 0 {
- gap = gap.NextGap()
- continue
- }
- pinnedPages = true
- gap = pb.Insert(gap, common, noValue{}).NextGap()
- }
- return pinnedPages
-}
-
-// UnpinRange unpins all pages in the specified range.
-func (pb *PinBoard) UnpinRange(r Range) {
- for seg := pb.LowerBoundSegment(r.Start); seg.Ok() && seg.Start() < r.End; {
- common := seg.Range().Intersect(r)
- if common.Length() == 0 {
- seg = seg.NextSegment()
- continue
- }
- seg = pb.RemoveRange(common).NextSegment()
- }
-}
-
-// RangePinnedStatus returns false if there's at least one unpinned page in the
-// specified range.
-func (pb *PinBoard) RangePinnedStatus(r Range) bool {
- for gap := pb.LowerBoundGap(r.Start); gap.Ok() && gap.Start() < r.End; {
- common := gap.Range().Intersect(r)
- if common.Length() == 0 {
- gap = gap.NextGap()
- continue
- }
- return false
- }
- return true
-}
-
-// RangeFromAshmemPin converts ashmem's original pin structure
-// to Range.
-func RangeFromAshmemPin(ap linux.AshmemPin) Range {
- if ap.Len == 0 {
- return Range{
- uint64(ap.Offset),
- maxUint64,
- }
- }
- return Range{
- uint64(ap.Offset),
- uint64(ap.Offset) + uint64(ap.Len),
- }
-}
diff --git a/pkg/sentry/fs/ashmem/pin_board_test.go b/pkg/sentry/fs/ashmem/pin_board_test.go
deleted file mode 100644
index 1ccd38f56..000000000
--- a/pkg/sentry/fs/ashmem/pin_board_test.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package ashmem
-
-import (
- "testing"
-
- "gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/usermem"
-)
-
-func TestPinBoard(t *testing.T) {
- pb := NewPinBoard()
-
- // Confirm that all pages are pinned.
- if !pb.RangePinnedStatus(RangeFromAshmemPin(linux.AshmemPin{0, 0})) {
- t.Errorf("RangePinnedStatus(all pages) returned false (unpinned) at start.")
- }
-
- // Unpin pages [1, 11) (counting from 0)
- pb.UnpinRange(RangeFromAshmemPin(linux.AshmemPin{
- usermem.PageSize,
- usermem.PageSize * 10,
- }))
-
- // Confirm that pages [1, 11) are unpinned and that page 0 and pages
- // larger than 10 are pinned.
- pinned := []linux.AshmemPin{
- {
- 0,
- usermem.PageSize,
- }, {
- usermem.PageSize * 11,
- 0,
- },
- }
-
- for _, pin := range pinned {
- if !pb.RangePinnedStatus(RangeFromAshmemPin(pin)) {
- t.Errorf("RangePinnedStatus(AshmemPin{offset (pages): %v, len (pages): %v}) returned false (unpinned).",
- pin.Offset, pin.Len)
- }
- }
-
- unpinned := []linux.AshmemPin{
- {
- usermem.PageSize,
- usermem.PageSize * 10,
- },
- }
-
- for _, pin := range unpinned {
- if pb.RangePinnedStatus(RangeFromAshmemPin(pin)) {
- t.Errorf("RangePinnedStatus(AshmemPin{offset (pages): %v, len (pages): %v}) returned true (pinned).",
- pin.Offset, pin.Len)
- }
- }
-
- // Pin pages [2, 6).
- pb.PinRange(RangeFromAshmemPin(linux.AshmemPin{
- usermem.PageSize * 2,
- usermem.PageSize * 4,
- }))
-
- // Confirm that pages 0, [2, 6) and pages larger than 10 are pinned
- // while others remain unpinned.
- pinned = []linux.AshmemPin{
- {
- 0,
- usermem.PageSize,
- },
- {
- usermem.PageSize * 2,
- usermem.PageSize * 4,
- },
- {
- usermem.PageSize * 11,
- 0,
- },
- }
-
- for _, pin := range pinned {
- if !pb.RangePinnedStatus(RangeFromAshmemPin(pin)) {
- t.Errorf("RangePinnedStatus(AshmemPin{offset (pages): %v, len (pages): %v}) returned false (unpinned).",
- pin.Offset, pin.Len)
- }
- }
-
- unpinned = []linux.AshmemPin{
- {
- usermem.PageSize,
- usermem.PageSize,
- }, {
- usermem.PageSize * 6,
- usermem.PageSize * 5,
- },
- }
-
- for _, pin := range unpinned {
- if pb.RangePinnedStatus(RangeFromAshmemPin(pin)) {
- t.Errorf("RangePinnedStatus(AshmemPin{offset (pages): %v, len (pages): %v}) returned true (pinned).",
- pin.Offset, pin.Len)
- }
- }
-
- // Status of a partially pinned range is unpinned.
- if pb.RangePinnedStatus(RangeFromAshmemPin(linux.AshmemPin{0, 0})) {
- t.Errorf("RangePinnedStatus(all pages) returned true (pinned).")
- }
-
- // Pin the whole range again.
- pb.PinRange(RangeFromAshmemPin(linux.AshmemPin{0, 0}))
-
- // Confirm that all pages are pinned.
- if !pb.RangePinnedStatus(RangeFromAshmemPin(linux.AshmemPin{0, 0})) {
- t.Errorf("RangePinnedStatus(all pages) returned false (unpinned) at start.")
- }
-}
diff --git a/pkg/sentry/fs/binder/BUILD b/pkg/sentry/fs/binder/BUILD
deleted file mode 100644
index 639a5603a..000000000
--- a/pkg/sentry/fs/binder/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-package(licenses = ["notice"])
-
-load("//tools/go_stateify:defs.bzl", "go_library")
-
-go_library(
- name = "binder",
- srcs = [
- "binder.go",
- ],
- importpath = "gvisor.dev/gvisor/pkg/sentry/fs/binder",
- visibility = ["//pkg/sentry:internal"],
- deps = [
- "//pkg/abi/linux",
- "//pkg/sentry/arch",
- "//pkg/sentry/context",
- "//pkg/sentry/fs",
- "//pkg/sentry/fs/fsutil",
- "//pkg/sentry/kernel",
- "//pkg/sentry/memmap",
- "//pkg/sentry/pgalloc",
- "//pkg/sentry/platform",
- "//pkg/sentry/usage",
- "//pkg/sentry/usermem",
- "//pkg/syserror",
- "//pkg/waiter",
- ],
-)
diff --git a/pkg/sentry/fs/binder/binder.go b/pkg/sentry/fs/binder/binder.go
deleted file mode 100644
index eef54d787..000000000
--- a/pkg/sentry/fs/binder/binder.go
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package binder implements Android Binder IPC module.
-package binder
-
-import (
- "sync"
-
- "gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/arch"
- "gvisor.dev/gvisor/pkg/sentry/context"
- "gvisor.dev/gvisor/pkg/sentry/fs"
- "gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
- "gvisor.dev/gvisor/pkg/sentry/kernel"
- "gvisor.dev/gvisor/pkg/sentry/memmap"
- "gvisor.dev/gvisor/pkg/sentry/pgalloc"
- "gvisor.dev/gvisor/pkg/sentry/platform"
- "gvisor.dev/gvisor/pkg/sentry/usage"
- "gvisor.dev/gvisor/pkg/sentry/usermem"
- "gvisor.dev/gvisor/pkg/syserror"
- "gvisor.dev/gvisor/pkg/waiter"
-)
-
-const (
- currentProtocolVersion = 8
-
- // mmapSizeLimit is the upper limit for mapped memory size in Binder.
- mmapSizeLimit = 4 * 1024 * 1024 // 4MB
-)
-
-// Device implements fs.InodeOperations.
-//
-// +stateify savable
-type Device struct {
- fsutil.InodeGenericChecker `state:"nosave"`
- fsutil.InodeNoExtendedAttributes `state:"nosave"`
- fsutil.InodeNoopAllocate `state:"nosave"`
- fsutil.InodeNoopRelease `state:"nosave"`
- fsutil.InodeNoopTruncate `state:"nosave"`
- fsutil.InodeNoopWriteOut `state:"nosave"`
- fsutil.InodeNotDirectory `state:"nosave"`
- fsutil.InodeNotMappable `state:"nosave"`
- fsutil.InodeNotSocket `state:"nosave"`
- fsutil.InodeNotSymlink `state:"nosave"`
- fsutil.InodeVirtual `state:"nosave"`
-
- fsutil.InodeSimpleAttributes
-}
-
-var _ fs.InodeOperations = (*Device)(nil)
-
-// NewDevice creates and initializes a Device structure.
-func NewDevice(ctx context.Context, owner fs.FileOwner, fp fs.FilePermissions) *Device {
- return &Device{
- InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fp, 0),
- }
-}
-
-// GetFile implements fs.InodeOperations.GetFile.
-//
-// TODO(b/30946773): Add functionality to GetFile: Additional fields will be
-// needed in the Device structure, initialize them here. Also, Device will need
-// to keep track of the created Procs in order to implement BINDER_READ_WRITE
-// ioctl.
-func (bd *Device) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
- return fs.NewFile(ctx, d, flags, &Proc{
- bd: bd,
- task: kernel.TaskFromContext(ctx),
- mfp: pgalloc.MemoryFileProviderFromContext(ctx),
- }), nil
-}
-
-// Proc implements fs.FileOperations and fs.IoctlGetter.
-//
-// +stateify savable
-type Proc struct {
- fsutil.FileNoFsync `state:"nosave"`
- fsutil.FileNoSplice `state:"nosave"`
- fsutil.FileNotDirReaddir `state:"nosave"`
- fsutil.FileUseInodeUnstableAttr `state:"nosave"`
- waiter.AlwaysReady `state:"nosave"`
-
- bd *Device
- task *kernel.Task
- mfp pgalloc.MemoryFileProvider
-
- // mu protects fr.
- mu sync.Mutex `state:"nosave"`
-
- // mapped is memory allocated from mfp.MemoryFile() by AddMapping.
- mapped platform.FileRange
-}
-
-// Release implements fs.FileOperations.Release.
-func (bp *Proc) Release() {
- bp.mu.Lock()
- defer bp.mu.Unlock()
- if bp.mapped.Length() != 0 {
- bp.mfp.MemoryFile().DecRef(bp.mapped)
- }
-}
-
-// Seek implements fs.FileOperations.Seek.
-//
-// Binder doesn't support seek operation (unless in debug mode).
-func (bp *Proc) Seek(ctx context.Context, file *fs.File, whence fs.SeekWhence, offset int64) (int64, error) {
- return offset, syserror.EOPNOTSUPP
-}
-
-// Read implements fs.FileOperations.Read.
-//
-// Binder doesn't support read operation (unless in debug mode).
-func (bp *Proc) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
- return 0, syserror.EOPNOTSUPP
-}
-
-// Write implements fs.FileOperations.Write.
-//
-// Binder doesn't support write operation.
-func (bp *Proc) Write(ctx context.Context, file *fs.File, src usermem.IOSequence, offset int64) (int64, error) {
- return 0, syserror.EOPNOTSUPP
-}
-
-// Flush implements fs.FileOperations.Flush.
-//
-// TODO(b/30946773): Implement.
-func (bp *Proc) Flush(ctx context.Context, file *fs.File) error {
- return nil
-}
-
-// ConfigureMMap implements fs.FileOperations.ConfigureMMap.
-func (bp *Proc) ConfigureMMap(ctx context.Context, file *fs.File, opts *memmap.MMapOpts) error {
- // Compare drivers/android/binder.c:binder_mmap().
- if caller := kernel.TaskFromContext(ctx); caller != bp.task {
- return syserror.EINVAL
- }
- if opts.Length > mmapSizeLimit {
- opts.Length = mmapSizeLimit
- }
- opts.MaxPerms.Write = false
-
- // TODO(b/30946773): Binder sets VM_DONTCOPY, preventing the created vma
- // from being copied across fork(), but we don't support this yet. As
- // a result, MMs containing a Binder mapping cannot be forked (MM.Fork will
- // fail when AddMapping returns EBUSY).
-
- return fsutil.GenericConfigureMMap(file, bp, opts)
-}
-
-// Ioctl implements fs.FileOperations.Ioctl.
-//
-// TODO(b/30946773): Implement.
-func (bp *Proc) Ioctl(ctx context.Context, _ *fs.File, io usermem.IO, args arch.SyscallArguments) (uintptr, error) {
- // Switch on ioctl request.
- switch uint32(args[1].Int()) {
- case linux.BinderVersionIoctl:
- ver := &linux.BinderVersion{
- ProtocolVersion: currentProtocolVersion,
- }
- // Copy result to user-space.
- _, err := usermem.CopyObjectOut(ctx, io, args[2].Pointer(), ver, usermem.IOOpts{
- AddressSpaceActive: true,
- })
- return 0, err
- case linux.BinderWriteReadIoctl:
- // TODO(b/30946773): Implement.
- fallthrough
- case linux.BinderSetIdleTimeoutIoctl:
- // TODO(b/30946773): Implement.
- fallthrough
- case linux.BinderSetMaxThreadsIoctl:
- // TODO(b/30946773): Implement.
- fallthrough
- case linux.BinderSetIdlePriorityIoctl:
- // TODO(b/30946773): Implement.
- fallthrough
- case linux.BinderSetContextMgrIoctl:
- // TODO(b/30946773): Implement.
- fallthrough
- case linux.BinderThreadExitIoctl:
- // TODO(b/30946773): Implement.
- return 0, syserror.ENOSYS
- default:
- // Ioctls irrelevant to Binder.
- return 0, syserror.EINVAL
- }
-}
-
-// AddMapping implements memmap.Mappable.AddMapping.
-func (bp *Proc) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar usermem.AddrRange, offset uint64, _ bool) error {
- bp.mu.Lock()
- defer bp.mu.Unlock()
- if bp.mapped.Length() != 0 {
- // mmap has been called before, which binder_mmap() doesn't like.
- return syserror.EBUSY
- }
- // Binder only allocates and maps a single page up-front
- // (drivers/android/binder.c:binder_mmap() => binder_update_page_range()).
- fr, err := bp.mfp.MemoryFile().Allocate(usermem.PageSize, usage.Anonymous)
- if err != nil {
- return err
- }
- bp.mapped = fr
- return nil
-}
-
-// RemoveMapping implements memmap.Mappable.RemoveMapping.
-func (*Proc) RemoveMapping(context.Context, memmap.MappingSpace, usermem.AddrRange, uint64, bool) {
- // Nothing to do. Notably, we don't free bp.mapped to allow another mmap.
-}
-
-// CopyMapping implements memmap.Mappable.CopyMapping.
-func (bp *Proc) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR usermem.AddrRange, offset uint64, _ bool) error {
- // Nothing to do. Notably, this is one case where CopyMapping isn't
- // equivalent to AddMapping, as AddMapping would return EBUSY.
- return nil
-}
-
-// Translate implements memmap.Mappable.Translate.
-func (bp *Proc) Translate(ctx context.Context, required, optional memmap.MappableRange, at usermem.AccessType) ([]memmap.Translation, error) {
- // TODO(b/30946773): In addition to the page initially allocated and mapped
- // in AddMapping (Linux: binder_mmap), Binder allocates and maps pages for
- // each transaction (Linux: binder_ioctl => binder_ioctl_write_read =>
- // binder_thread_write => binder_transaction => binder_alloc_buf =>
- // binder_update_page_range). Since we don't actually implement
- // BinderWriteReadIoctl (Linux: BINDER_WRITE_READ), we only ever have the
- // first page.
- var err error
- if required.End > usermem.PageSize {
- err = &memmap.BusError{syserror.EFAULT}
- }
- if required.Start == 0 {
- return []memmap.Translation{
- {
- Source: memmap.MappableRange{0, usermem.PageSize},
- File: bp.mfp.MemoryFile(),
- Offset: bp.mapped.Start,
- Perms: usermem.AnyAccess,
- },
- }, err
- }
- return nil, err
-}
-
-// InvalidateUnsavable implements memmap.Mappable.InvalidateUnsavable.
-func (bp *Proc) InvalidateUnsavable(ctx context.Context) error {
- return nil
-}
diff --git a/pkg/sentry/fs/dev/BUILD b/pkg/sentry/fs/dev/BUILD
index a9b03d172..59de615fb 100644
--- a/pkg/sentry/fs/dev/BUILD
+++ b/pkg/sentry/fs/dev/BUILD
@@ -20,8 +20,6 @@ go_library(
"//pkg/sentry/context",
"//pkg/sentry/device",
"//pkg/sentry/fs",
- "//pkg/sentry/fs/ashmem",
- "//pkg/sentry/fs/binder",
"//pkg/sentry/fs/fsutil",
"//pkg/sentry/fs/ramfs",
"//pkg/sentry/fs/tmpfs",
diff --git a/pkg/sentry/fs/dev/dev.go b/pkg/sentry/fs/dev/dev.go
index fb6c30ff0..d4bbd9807 100644
--- a/pkg/sentry/fs/dev/dev.go
+++ b/pkg/sentry/fs/dev/dev.go
@@ -20,8 +20,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/context"
"gvisor.dev/gvisor/pkg/sentry/fs"
- "gvisor.dev/gvisor/pkg/sentry/fs/ashmem"
- "gvisor.dev/gvisor/pkg/sentry/fs/binder"
"gvisor.dev/gvisor/pkg/sentry/fs/ramfs"
"gvisor.dev/gvisor/pkg/sentry/fs/tmpfs"
"gvisor.dev/gvisor/pkg/sentry/usermem"
@@ -81,7 +79,7 @@ func newSymlink(ctx context.Context, target string, msrc *fs.MountSource) *fs.In
}
// New returns the root node of a device filesystem.
-func New(ctx context.Context, msrc *fs.MountSource, binderEnabled bool, ashmemEnabled bool) *fs.Inode {
+func New(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
contents := map[string]*fs.Inode{
"fd": newSymlink(ctx, "/proc/self/fd", msrc),
"stdin": newSymlink(ctx, "/proc/self/fd/0", msrc),
@@ -118,16 +116,6 @@ func New(ctx context.Context, msrc *fs.MountSource, binderEnabled bool, ashmemEn
"ptmx": newSymlink(ctx, "pts/ptmx", msrc),
}
- if binderEnabled {
- binder := binder.NewDevice(ctx, fs.RootOwner, fs.FilePermsFromMode(0666))
- contents["binder"] = newCharacterDevice(ctx, binder, msrc)
- }
-
- if ashmemEnabled {
- ashmem := ashmem.NewDevice(ctx, fs.RootOwner, fs.FilePermsFromMode(0666))
- contents["ashmem"] = newCharacterDevice(ctx, ashmem, msrc)
- }
-
iops := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555))
return fs.NewInode(ctx, iops, msrc, fs.StableAttr{
DeviceID: devDevice.DeviceID(),
diff --git a/pkg/sentry/fs/dev/fs.go b/pkg/sentry/fs/dev/fs.go
index cbc2c2f9b..55f8af704 100644
--- a/pkg/sentry/fs/dev/fs.go
+++ b/pkg/sentry/fs/dev/fs.go
@@ -15,19 +15,10 @@
package dev
import (
- "strconv"
-
"gvisor.dev/gvisor/pkg/sentry/context"
"gvisor.dev/gvisor/pkg/sentry/fs"
- "gvisor.dev/gvisor/pkg/syserror"
)
-// Optional key containing boolean flag which specifies if Android Binder IPC should be enabled.
-const binderEnabledKey = "binder_enabled"
-
-// Optional key containing boolean flag which specifies if Android ashmem should be enabled.
-const ashmemEnabledKey = "ashmem_enabled"
-
// filesystem is a devtmpfs.
//
// +stateify savable
@@ -67,33 +58,7 @@ func (*filesystem) Flags() fs.FilesystemFlags {
// Mount returns a devtmpfs root that can be positioned in the vfs.
func (f *filesystem) Mount(ctx context.Context, device string, flags fs.MountSourceFlags, data string, _ interface{}) (*fs.Inode, error) {
- // device is always ignored.
// devtmpfs backed by ramfs ignores bad options. See fs/ramfs/inode.c:ramfs_parse_options.
// -> we should consider parsing the mode and backing devtmpfs by this.
-
- // Parse generic comma-separated key=value options.
- options := fs.GenericMountSourceOptions(data)
-
- // binerEnabledKey is optional and binder is disabled by default.
- binderEnabled := false
- if beStr, exists := options[binderEnabledKey]; exists {
- var err error
- binderEnabled, err = strconv.ParseBool(beStr)
- if err != nil {
- return nil, syserror.EINVAL
- }
- }
-
- // ashmemEnabledKey is optional and ashmem is disabled by default.
- ashmemEnabled := false
- if aeStr, exists := options[ashmemEnabledKey]; exists {
- var err error
- ashmemEnabled, err = strconv.ParseBool(aeStr)
- if err != nil {
- return nil, syserror.EINVAL
- }
- }
-
- // Construct the devtmpfs root.
- return New(ctx, fs.NewNonCachingMountSource(ctx, f, flags), binderEnabled, ashmemEnabled), nil
+ return New(ctx, fs.NewNonCachingMountSource(ctx, f, flags)), nil
}