summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/memmap
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2020-07-27 19:03:14 +0000
committergVisor bot <gvisor-bot@google.com>2020-07-27 19:03:14 +0000
commit849e740a83ea9d5c52f727ec4c0169b42f55287b (patch)
treea4d9b30737158343f53f046ffc72deacc1117f4f /pkg/sentry/memmap
parentbd34346f555b8ecb00b5eb06dedf8ec95904dd13 (diff)
parentf347a578b79c96c13ed492b2cf9aec1cb3e60f3f (diff)
Merge release-20200622.1-232-gf347a578b (automated)
Diffstat (limited to 'pkg/sentry/memmap')
-rw-r--r--pkg/sentry/memmap/file_range.go62
-rw-r--r--pkg/sentry/memmap/memmap.go60
-rw-r--r--pkg/sentry/memmap/memmap_state_autogen.go27
3 files changed, 142 insertions, 7 deletions
diff --git a/pkg/sentry/memmap/file_range.go b/pkg/sentry/memmap/file_range.go
new file mode 100644
index 000000000..e4c852a66
--- /dev/null
+++ b/pkg/sentry/memmap/file_range.go
@@ -0,0 +1,62 @@
+package memmap
+
+// A Range represents a contiguous range of T.
+//
+// +stateify savable
+type FileRange struct {
+ // Start is the inclusive start of the range.
+ Start uint64
+
+ // End is the exclusive end of the range.
+ End uint64
+}
+
+// WellFormed returns true if r.Start <= r.End. All other methods on a Range
+// require that the Range is well-formed.
+func (r FileRange) WellFormed() bool {
+ return r.Start <= r.End
+}
+
+// Length returns the length of the range.
+func (r FileRange) Length() uint64 {
+ return r.End - r.Start
+}
+
+// Contains returns true if r contains x.
+func (r FileRange) Contains(x uint64) bool {
+ return r.Start <= x && x < r.End
+}
+
+// Overlaps returns true if r and r2 overlap.
+func (r FileRange) Overlaps(r2 FileRange) bool {
+ return r.Start < r2.End && r2.Start < r.End
+}
+
+// IsSupersetOf returns true if r is a superset of r2; that is, the range r2 is
+// contained within r.
+func (r FileRange) IsSupersetOf(r2 FileRange) bool {
+ return r.Start <= r2.Start && r.End >= r2.End
+}
+
+// Intersect returns a range consisting of the intersection between r and r2.
+// If r and r2 do not overlap, Intersect returns a range with unspecified
+// bounds, but for which Length() == 0.
+func (r FileRange) Intersect(r2 FileRange) FileRange {
+ if r.Start < r2.Start {
+ r.Start = r2.Start
+ }
+ if r.End > r2.End {
+ r.End = r2.End
+ }
+ if r.End < r.Start {
+ r.End = r.Start
+ }
+ return r
+}
+
+// CanSplitAt returns true if it is legal to split a segment spanning the range
+// r at x; that is, splitting at x would produce two ranges, both of which have
+// non-zero length.
+func (r FileRange) CanSplitAt(x uint64) bool {
+ return r.Contains(x) && r.Start < x
+}
diff --git a/pkg/sentry/memmap/memmap.go b/pkg/sentry/memmap/memmap.go
index c6db9fc8f..c188f6c29 100644
--- a/pkg/sentry/memmap/memmap.go
+++ b/pkg/sentry/memmap/memmap.go
@@ -19,12 +19,12 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/context"
- "gvisor.dev/gvisor/pkg/sentry/platform"
+ "gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/usermem"
)
// Mappable represents a memory-mappable object, a mutable mapping from uint64
-// offsets to (platform.File, uint64 File offset) pairs.
+// offsets to (File, uint64 File offset) pairs.
//
// See mm/mm.go for Mappable's place in the lock order.
//
@@ -74,7 +74,7 @@ type Mappable interface {
// Translations are valid until invalidated by a callback to
// MappingSpace.Invalidate or until the caller removes its mapping of the
// translated range. Mappable implementations must ensure that at least one
- // reference is held on all pages in a platform.File that may be the result
+ // reference is held on all pages in a File that may be the result
// of a valid Translation.
//
// Preconditions: required.Length() > 0. optional.IsSupersetOf(required).
@@ -100,7 +100,7 @@ type Translation struct {
Source MappableRange
// File is the mapped file.
- File platform.File
+ File File
// Offset is the offset into File at which this Translation begins.
Offset uint64
@@ -110,9 +110,9 @@ type Translation struct {
Perms usermem.AccessType
}
-// FileRange returns the platform.FileRange represented by t.
-func (t Translation) FileRange() platform.FileRange {
- return platform.FileRange{t.Offset, t.Offset + t.Source.Length()}
+// FileRange returns the FileRange represented by t.
+func (t Translation) FileRange() FileRange {
+ return FileRange{t.Offset, t.Offset + t.Source.Length()}
}
// CheckTranslateResult returns an error if (ts, terr) does not satisfy all
@@ -361,3 +361,49 @@ type MMapOpts struct {
// TODO(jamieliu): Replace entirely with MappingIdentity?
Hint string
}
+
+// File represents a host file that may be mapped into an platform.AddressSpace.
+type File interface {
+ // All pages in a File are reference-counted.
+
+ // IncRef increments the reference count on all pages in fr.
+ //
+ // Preconditions: fr.Start and fr.End must be page-aligned. fr.Length() >
+ // 0. At least one reference must be held on all pages in fr. (The File
+ // interface does not provide a way to acquire an initial reference;
+ // implementors may define mechanisms for doing so.)
+ IncRef(fr FileRange)
+
+ // DecRef decrements the reference count on all pages in fr.
+ //
+ // Preconditions: fr.Start and fr.End must be page-aligned. fr.Length() >
+ // 0. At least one reference must be held on all pages in fr.
+ DecRef(fr FileRange)
+
+ // MapInternal returns a mapping of the given file offsets in the invoking
+ // process' address space for reading and writing.
+ //
+ // Note that fr.Start and fr.End need not be page-aligned.
+ //
+ // Preconditions: fr.Length() > 0. At least one reference must be held on
+ // all pages in fr.
+ //
+ // Postconditions: The returned mapping is valid as long as at least one
+ // reference is held on the mapped pages.
+ MapInternal(fr FileRange, at usermem.AccessType) (safemem.BlockSeq, error)
+
+ // FD returns the file descriptor represented by the File.
+ //
+ // The only permitted operation on the returned file descriptor is to map
+ // pages from it consistent with the requirements of AddressSpace.MapFile.
+ FD() int
+}
+
+// FileRange represents a range of uint64 offsets into a File.
+//
+// type FileRange <generated using go_generics>
+
+// String implements fmt.Stringer.String.
+func (fr FileRange) String() string {
+ return fmt.Sprintf("[%#x, %#x)", fr.Start, fr.End)
+}
diff --git a/pkg/sentry/memmap/memmap_state_autogen.go b/pkg/sentry/memmap/memmap_state_autogen.go
index d7cd50786..4feb2eb66 100644
--- a/pkg/sentry/memmap/memmap_state_autogen.go
+++ b/pkg/sentry/memmap/memmap_state_autogen.go
@@ -6,6 +6,32 @@ import (
"gvisor.dev/gvisor/pkg/state"
)
+func (x *FileRange) StateTypeName() string {
+ return "pkg/sentry/memmap.FileRange"
+}
+
+func (x *FileRange) StateFields() []string {
+ return []string{
+ "Start",
+ "End",
+ }
+}
+
+func (x *FileRange) beforeSave() {}
+
+func (x *FileRange) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Start)
+ m.Save(1, &x.End)
+}
+
+func (x *FileRange) afterLoad() {}
+
+func (x *FileRange) StateLoad(m state.Source) {
+ m.Load(0, &x.Start)
+ m.Load(1, &x.End)
+}
+
func (x *MappableRange) StateTypeName() string {
return "pkg/sentry/memmap.MappableRange"
}
@@ -62,6 +88,7 @@ func (x *MappingOfRange) StateLoad(m state.Source) {
}
func init() {
+ state.Register((*FileRange)(nil))
state.Register((*MappableRange)(nil))
state.Register((*MappingOfRange)(nil))
}