Skip to content

Commit

Permalink
[vfs2] Remove VFS1 usage in VDSO.
Browse files Browse the repository at this point in the history
Removed VDSO dependency on VFS1.

Resolves #2921

PiperOrigin-RevId: 320122176
  • Loading branch information
ayushr2 authored and gvisor-bot committed Jul 8, 2020
1 parent 5e05950 commit efa2615
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 84 deletions.
2 changes: 1 addition & 1 deletion pkg/sentry/fsimpl/testutil/kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func Boot() (*kernel.Kernel, error) {
k.SetMemoryFile(mf)

// Pass k as the platform since it is savable, unlike the actual platform.
vdso, err := loader.PrepareVDSO(nil, k)
vdso, err := loader.PrepareVDSO(k)
if err != nil {
return nil, fmt.Errorf("creating vdso: %v", err)
}
Expand Down
4 changes: 0 additions & 4 deletions pkg/sentry/loader/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ go_library(
"//pkg/rand",
"//pkg/safemem",
"//pkg/sentry/arch",
"//pkg/sentry/fs",
"//pkg/sentry/fs/anon",
"//pkg/sentry/fs/fsutil",
"//pkg/sentry/fsbridge",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/limits",
Expand All @@ -45,6 +42,5 @@ go_library(
"//pkg/syserr",
"//pkg/syserror",
"//pkg/usermem",
"//pkg/waiter",
],
)
15 changes: 12 additions & 3 deletions pkg/sentry/loader/elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,23 @@ type elfInfo struct {
sharedObject bool
}

// fullReader interface extracts the ReadFull method from fsbridge.File so that
// client code does not need to define an entire fsbridge.File when only read
// functionality is needed.
//
// TODO(gvisor.dev/issue/1035): Once VFS2 ships, rewrite this to wrap
// vfs.FileDescription's PRead/Read instead.
type fullReader interface {
// ReadFull is the same as fsbridge.File.ReadFull.
ReadFull(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error)
}

// parseHeader parse the ELF header, verifying that this is a supported ELF
// file and returning the ELF program headers.
//
// This is similar to elf.NewFile, except that it is more strict about what it
// accepts from the ELF, and it doesn't parse unnecessary parts of the file.
//
// ctx may be nil if f does not need it.
func parseHeader(ctx context.Context, f fsbridge.File) (elfInfo, error) {
func parseHeader(ctx context.Context, f fullReader) (elfInfo, error) {
// Check ident first; it will tell us the endianness of the rest of the
// structs.
var ident [elf.EI_NIDENT]byte
Expand Down
17 changes: 0 additions & 17 deletions pkg/sentry/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"gvisor.dev/gvisor/pkg/cpuid"
"gvisor.dev/gvisor/pkg/rand"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fsbridge"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/mm"
Expand Down Expand Up @@ -80,22 +79,6 @@ type LoadArgs struct {
Features *cpuid.FeatureSet
}

// readFull behaves like io.ReadFull for an *fs.File.
func readFull(ctx context.Context, f *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
var total int64
for dst.NumBytes() > 0 {
n, err := f.Preadv(ctx, dst, offset+total)
total += n
if err == io.EOF && total != 0 {
return total, io.ErrUnexpectedEOF
} else if err != nil {
return total, err
}
dst = dst.DropFirst64(n)
}
return total, nil
}

// openPath opens args.Filename and checks that it is valid for loading.
//
// openPath returns an *fs.Dirent and *fs.File for args.Filename, which is not
Expand Down
61 changes: 5 additions & 56 deletions pkg/sentry/loader/vdso.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,13 @@ import (
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/anon"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
"gvisor.dev/gvisor/pkg/sentry/fsbridge"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/mm"
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
"gvisor.dev/gvisor/pkg/sentry/uniqueid"
"gvisor.dev/gvisor/pkg/sentry/usage"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
)

const vdsoPrelink = 0xffffffffff700000
Expand All @@ -55,52 +50,11 @@ func (f *fileContext) Value(key interface{}) interface{} {
}
}

// byteReader implements fs.FileOperations for reading from a []byte source.
type byteReader struct {
fsutil.FileNoFsync `state:"nosave"`
fsutil.FileNoIoctl `state:"nosave"`
fsutil.FileNoMMap `state:"nosave"`
fsutil.FileNoSplice `state:"nosave"`
fsutil.FileNoopFlush `state:"nosave"`
fsutil.FileNoopRelease `state:"nosave"`
fsutil.FileNotDirReaddir `state:"nosave"`
fsutil.FilePipeSeek `state:"nosave"`
fsutil.FileUseInodeUnstableAttr `state:"nosave"`
waiter.AlwaysReady `state:"nosave"`

type byteFullReader struct {
data []byte
}

var _ fs.FileOperations = (*byteReader)(nil)

// newByteReaderFile creates a fake file to read data from.
//
// TODO(gvisor.dev/issue/2921): Convert to VFS2.
func newByteReaderFile(ctx context.Context, data []byte) *fs.File {
// Create a fake inode.
inode := fs.NewInode(
ctx,
&fsutil.SimpleFileInode{},
fs.NewPseudoMountSource(ctx),
fs.StableAttr{
Type: fs.Anonymous,
DeviceID: anon.PseudoDevice.DeviceID(),
InodeID: anon.PseudoDevice.NextIno(),
BlockSize: usermem.PageSize,
})

// Use the fake inode to create a fake dirent.
dirent := fs.NewTransientDirent(inode)
defer dirent.DecRef()

// Use the fake dirent to make a fake file.
flags := fs.FileFlags{Read: true, Pread: true}
return fs.NewFile(&fileContext{Context: context.Background()}, dirent, flags, &byteReader{
data: data,
})
}

func (b *byteReader) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
func (b *byteFullReader) ReadFull(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
if offset < 0 {
return 0, syserror.EINVAL
}
Expand All @@ -111,10 +65,6 @@ func (b *byteReader) Read(ctx context.Context, file *fs.File, dst usermem.IOSequ
return int64(n), err
}

func (b *byteReader) Write(ctx context.Context, file *fs.File, src usermem.IOSequence, offset int64) (int64, error) {
panic("Write not supported")
}

// validateVDSO checks that the VDSO can be loaded by loadVDSO.
//
// VDSOs are special (see below). Since we are going to map the VDSO directly
Expand All @@ -130,7 +80,7 @@ func (b *byteReader) Write(ctx context.Context, file *fs.File, src usermem.IOSeq
// * PT_LOAD segments don't extend beyond the end of the file.
//
// ctx may be nil if f does not need it.
func validateVDSO(ctx context.Context, f fsbridge.File, size uint64) (elfInfo, error) {
func validateVDSO(ctx context.Context, f fullReader, size uint64) (elfInfo, error) {
info, err := parseHeader(ctx, f)
if err != nil {
log.Infof("Unable to parse VDSO header: %v", err)
Expand Down Expand Up @@ -248,13 +198,12 @@ func getSymbolValueFromVDSO(symbol string) (uint64, error) {

// PrepareVDSO validates the system VDSO and returns a VDSO, containing the
// param page for updating by the kernel.
func PrepareVDSO(ctx context.Context, mfp pgalloc.MemoryFileProvider) (*VDSO, error) {
vdsoFile := fsbridge.NewFSFile(newByteReaderFile(ctx, vdsoBin))
func PrepareVDSO(mfp pgalloc.MemoryFileProvider) (*VDSO, error) {
vdsoFile := &byteFullReader{data: vdsoBin}

// First make sure the VDSO is valid. vdsoFile does not use ctx, so a
// nil context can be passed.
info, err := validateVDSO(nil, vdsoFile, uint64(len(vdsoBin)))
vdsoFile.DecRef()
if err != nil {
return nil, err
}
Expand Down
4 changes: 1 addition & 3 deletions runsc/boot/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,7 @@ func New(args Args) (*Loader, error) {
// Create VDSO.
//
// Pass k as the platform since it is savable, unlike the actual platform.
//
// FIXME(b/109889800): Use non-nil context.
vdso, err := loader.PrepareVDSO(nil, k)
vdso, err := loader.PrepareVDSO(k)
if err != nil {
return nil, fmt.Errorf("creating vdso: %v", err)
}
Expand Down

0 comments on commit efa2615

Please sign in to comment.