mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[vfs2] Remove VFS1 usage in VDSO.
Removed VDSO dependency on VFS1. Resolves #2921 PiperOrigin-RevId: 320122176
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user