[vfs2] Remove VFS1 usage in VDSO.

Removed VDSO dependency on VFS1.

Resolves #2921

PiperOrigin-RevId: 320122176
This commit is contained in:
Ayush Ranjan
2020-07-07 21:37:08 -07:00
committed by gVisor bot
parent 5e05950c1c
commit efa2615eb0
6 changed files with 19 additions and 84 deletions
+1 -1
View File
@@ -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)
}
-4
View File
@@ -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",
@@ -45,6 +42,5 @@ go_library(
"//pkg/syserr",
"//pkg/syserror",
"//pkg/usermem",
"//pkg/waiter",
],
)
+12 -3
View File
@@ -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
-17
View File
@@ -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"
@@ -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
+5 -56
View File
@@ -26,10 +26,6 @@ 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"
@@ -37,7 +33,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/usage"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
)
const vdsoPrelink = 0xffffffffff700000
@@ -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
}
@@ -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
@@ -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)
@@ -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
}
+1 -3
View File
@@ -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)
}