diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/sentry/fs/attr.go | 44 | ||||
-rwxr-xr-x | pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo_unsafe.go | 4 | ||||
-rw-r--r-- | pkg/sentry/safemem/io.go | 55 | ||||
-rw-r--r-- | pkg/sentry/syscalls/linux/sys_getdents.go | 24 | ||||
-rwxr-xr-x | pkg/sentry/time/seqatomic_parameters_unsafe.go | 4 |
5 files changed, 103 insertions, 28 deletions
diff --git a/pkg/sentry/fs/attr.go b/pkg/sentry/fs/attr.go index 9fc6a5bc2..4f3d6410e 100644 --- a/pkg/sentry/fs/attr.go +++ b/pkg/sentry/fs/attr.go @@ -111,6 +111,50 @@ func (n InodeType) LinuxType() uint32 { } } +// ToDirentType converts an InodeType to a linux dirent type field. +func ToDirentType(nodeType InodeType) uint8 { + switch nodeType { + case RegularFile, SpecialFile: + return linux.DT_REG + case Symlink: + return linux.DT_LNK + case Directory, SpecialDirectory: + return linux.DT_DIR + case Pipe: + return linux.DT_FIFO + case CharacterDevice: + return linux.DT_CHR + case BlockDevice: + return linux.DT_BLK + case Socket: + return linux.DT_SOCK + default: + return linux.DT_UNKNOWN + } +} + +// ToInodeType coverts a linux file type to InodeType. +func ToInodeType(linuxFileType linux.FileMode) InodeType { + switch linuxFileType { + case linux.ModeRegular: + return RegularFile + case linux.ModeDirectory: + return Directory + case linux.ModeSymlink: + return Symlink + case linux.ModeNamedPipe: + return Pipe + case linux.ModeCharacterDevice: + return CharacterDevice + case linux.ModeBlockDevice: + return BlockDevice + case linux.ModeSocket: + return Socket + default: + panic(fmt.Sprintf("unknown file mode: %d", linuxFileType)) + } +} + // StableAttr contains Inode attributes that will be stable throughout the // lifetime of the Inode. // diff --git a/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo_unsafe.go b/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo_unsafe.go index 24528b66a..25ad17a4e 100755 --- a/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo_unsafe.go +++ b/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo_unsafe.go @@ -1,12 +1,12 @@ package kernel import ( + "fmt" + "reflect" "strings" "unsafe" - "fmt" "gvisor.dev/gvisor/third_party/gvsync" - "reflect" ) // SeqAtomicLoad returns a copy of *ptr, ensuring that the read does not race diff --git a/pkg/sentry/safemem/io.go b/pkg/sentry/safemem/io.go index 5c3d73eb7..f039a5c34 100644 --- a/pkg/sentry/safemem/io.go +++ b/pkg/sentry/safemem/io.go @@ -157,7 +157,8 @@ func (w ToIOWriter) Write(src []byte) (int, error) { } // FromIOReader implements Reader for an io.Reader by repeatedly invoking -// io.Reader.Read until it returns an error or partial read. +// io.Reader.Read until it returns an error or partial read. This is not +// thread-safe. // // FromIOReader will return a successful partial read iff Reader.Read does so. type FromIOReader struct { @@ -206,6 +207,58 @@ func (r FromIOReader) readToBlock(dst Block, buf []byte) (int, []byte, error) { return wbn, buf, rerr } +// FromIOReaderAt implements Reader for an io.ReaderAt. Does not repeatedly +// invoke io.ReaderAt.ReadAt because ReadAt is more strict than Read. A partial +// read indicates an error. This is not thread-safe. +type FromIOReaderAt struct { + ReaderAt io.ReaderAt + Offset int64 +} + +// ReadToBlocks implements Reader.ReadToBlocks. +func (r FromIOReaderAt) ReadToBlocks(dsts BlockSeq) (uint64, error) { + var buf []byte + var done uint64 + for !dsts.IsEmpty() { + dst := dsts.Head() + var n int + var err error + n, buf, err = r.readToBlock(dst, buf) + done += uint64(n) + if n != dst.Len() { + return done, err + } + dsts = dsts.Tail() + if err != nil { + if dsts.IsEmpty() && err == io.EOF { + return done, nil + } + return done, err + } + } + return done, nil +} + +func (r FromIOReaderAt) readToBlock(dst Block, buf []byte) (int, []byte, error) { + // io.Reader isn't safecopy-aware, so we have to buffer Blocks that require + // safecopy. + if !dst.NeedSafecopy() { + n, err := r.ReaderAt.ReadAt(dst.ToSlice(), r.Offset) + r.Offset += int64(n) + return n, buf, err + } + if len(buf) < dst.Len() { + buf = make([]byte, dst.Len()) + } + rn, rerr := r.ReaderAt.ReadAt(buf[:dst.Len()], r.Offset) + r.Offset += int64(rn) + wbn, wberr := Copy(dst, BlockFromSafeSlice(buf[:rn])) + if wberr != nil { + return wbn, buf, wberr + } + return wbn, buf, rerr +} + // FromIOWriter implements Writer for an io.Writer by repeatedly invoking // io.Writer.Write until it returns an error or partial write. // diff --git a/pkg/sentry/syscalls/linux/sys_getdents.go b/pkg/sentry/syscalls/linux/sys_getdents.go index 63e2c5a5d..912cbe4ff 100644 --- a/pkg/sentry/syscalls/linux/sys_getdents.go +++ b/pkg/sentry/syscalls/linux/sys_getdents.go @@ -120,7 +120,7 @@ func newDirent(width uint, name string, attr fs.DentAttr, offset uint64) *dirent Ino: attr.InodeID, Off: offset, }, - Typ: toType(attr.Type), + Typ: fs.ToDirentType(attr.Type), }, Name: []byte(name), } @@ -142,28 +142,6 @@ func smallestDirent64(a arch.Context) uint { return uint(binary.Size(d.Hdr)) + a.Width() } -// toType converts an fs.InodeOperationsInfo to a linux dirent typ field. -func toType(nodeType fs.InodeType) uint8 { - switch nodeType { - case fs.RegularFile, fs.SpecialFile: - return linux.DT_REG - case fs.Symlink: - return linux.DT_LNK - case fs.Directory, fs.SpecialDirectory: - return linux.DT_DIR - case fs.Pipe: - return linux.DT_FIFO - case fs.CharacterDevice: - return linux.DT_CHR - case fs.BlockDevice: - return linux.DT_BLK - case fs.Socket: - return linux.DT_SOCK - default: - return linux.DT_UNKNOWN - } -} - // padRec pads the name field until the rec length is a multiple of the width, // which must be a power of 2. It returns the padded rec length. func (d *dirent) padRec(width int) uint16 { diff --git a/pkg/sentry/time/seqatomic_parameters_unsafe.go b/pkg/sentry/time/seqatomic_parameters_unsafe.go index fb30a22c6..89792c56d 100755 --- a/pkg/sentry/time/seqatomic_parameters_unsafe.go +++ b/pkg/sentry/time/seqatomic_parameters_unsafe.go @@ -1,12 +1,12 @@ package time import ( + "fmt" + "reflect" "strings" "unsafe" - "fmt" "gvisor.dev/gvisor/third_party/gvsync" - "reflect" ) // SeqAtomicLoad returns a copy of *ptr, ensuring that the read does not race |