github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/memmap/mapping_set.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package memmap 16 17 import ( 18 "fmt" 19 "math" 20 21 "github.com/nicocha30/gvisor-ligolo/pkg/hostarch" 22 ) 23 24 // MappingSet maps offsets into a Mappable to mappings of those offsets. It is 25 // used to implement Mappable.AddMapping and RemoveMapping for Mappables that 26 // may need to call MappingSpace.Invalidate. 27 // 28 // type MappingSet <generated by go_generics> 29 30 // MappingsOfRange is the value type of MappingSet, and represents the set of 31 // all mappings of the corresponding MappableRange. 32 // 33 // Using a map offers O(1) lookups in RemoveMapping and 34 // mappingSetFunctions.Merge. 35 type MappingsOfRange map[MappingOfRange]struct{} 36 37 // MappingOfRange represents a mapping of a MappableRange. 38 // 39 // +stateify savable 40 type MappingOfRange struct { 41 MappingSpace MappingSpace 42 AddrRange hostarch.AddrRange 43 Writable bool 44 } 45 46 func (r MappingOfRange) invalidate(opts InvalidateOpts) { 47 r.MappingSpace.Invalidate(r.AddrRange, opts) 48 } 49 50 // String implements fmt.Stringer.String. 51 func (r MappingOfRange) String() string { 52 return fmt.Sprintf("%#v", r.AddrRange) 53 } 54 55 // mappingSetFunctions implements segment.Functions for MappingSet. 56 type mappingSetFunctions struct{} 57 58 // MinKey implements segment.Functions.MinKey. 59 func (mappingSetFunctions) MinKey() uint64 { 60 return 0 61 } 62 63 // MaxKey implements segment.Functions.MaxKey. 64 func (mappingSetFunctions) MaxKey() uint64 { 65 return math.MaxUint64 66 } 67 68 // ClearValue implements segment.Functions.ClearValue. 69 func (mappingSetFunctions) ClearValue(v *MappingsOfRange) { 70 *v = MappingsOfRange{} 71 } 72 73 // Merge implements segment.Functions.Merge. 74 // 75 // Since each value is a map of MappingOfRanges, values can only be merged if 76 // all MappingOfRanges in each map have an exact pair in the other map, forming 77 // one contiguous region. 78 func (mappingSetFunctions) Merge(r1 MappableRange, val1 MappingsOfRange, r2 MappableRange, val2 MappingsOfRange) (MappingsOfRange, bool) { 79 if len(val1) != len(val2) { 80 return nil, false 81 } 82 83 merged := make(MappingsOfRange, len(val1)) 84 85 // Each MappingOfRange in val1 must have a matching region in val2, forming 86 // one contiguous region. 87 for k1 := range val1 { 88 // We expect val2 to contain a key that forms a contiguous 89 // region with k1. 90 k2 := MappingOfRange{ 91 MappingSpace: k1.MappingSpace, 92 AddrRange: hostarch.AddrRange{ 93 Start: k1.AddrRange.End, 94 End: k1.AddrRange.End + hostarch.Addr(r2.Length()), 95 }, 96 Writable: k1.Writable, 97 } 98 if _, ok := val2[k2]; !ok { 99 return nil, false 100 } 101 102 // OK. Add it to the merged map. 103 merged[MappingOfRange{ 104 MappingSpace: k1.MappingSpace, 105 AddrRange: hostarch.AddrRange{ 106 Start: k1.AddrRange.Start, 107 End: k2.AddrRange.End, 108 }, 109 Writable: k1.Writable, 110 }] = struct{}{} 111 } 112 113 return merged, true 114 } 115 116 // Split implements segment.Functions.Split. 117 func (mappingSetFunctions) Split(r MappableRange, val MappingsOfRange, split uint64) (MappingsOfRange, MappingsOfRange) { 118 if split <= r.Start || split >= r.End { 119 panic(fmt.Sprintf("split is not within range %v", r)) 120 } 121 122 m1 := make(MappingsOfRange, len(val)) 123 m2 := make(MappingsOfRange, len(val)) 124 125 // split is a value in MappableRange, we need the offset into the 126 // corresponding MappingsOfRange. 127 offset := hostarch.Addr(split - r.Start) 128 for k := range val { 129 k1 := MappingOfRange{ 130 MappingSpace: k.MappingSpace, 131 AddrRange: hostarch.AddrRange{ 132 Start: k.AddrRange.Start, 133 End: k.AddrRange.Start + offset, 134 }, 135 Writable: k.Writable, 136 } 137 m1[k1] = struct{}{} 138 139 k2 := MappingOfRange{ 140 MappingSpace: k.MappingSpace, 141 AddrRange: hostarch.AddrRange{ 142 Start: k.AddrRange.Start + offset, 143 End: k.AddrRange.End, 144 }, 145 Writable: k.Writable, 146 } 147 m2[k2] = struct{}{} 148 } 149 150 return m1, m2 151 } 152 153 // subsetMapping returns the MappingOfRange that maps subsetRange, given that 154 // ms maps wholeRange beginning at addr. 155 // 156 // For instance, suppose wholeRange = [0x0, 0x2000) and addr = 0x4000, 157 // indicating that ms maps addresses [0x4000, 0x6000) to MappableRange [0x0, 158 // 0x2000). Then for subsetRange = [0x1000, 0x2000), subsetMapping returns a 159 // MappingOfRange for which AddrRange = [0x5000, 0x6000). 160 func subsetMapping(wholeRange, subsetRange MappableRange, ms MappingSpace, addr hostarch.Addr, writable bool) MappingOfRange { 161 if !wholeRange.IsSupersetOf(subsetRange) { 162 panic(fmt.Sprintf("%v is not a superset of %v", wholeRange, subsetRange)) 163 } 164 165 offset := subsetRange.Start - wholeRange.Start 166 start := addr + hostarch.Addr(offset) 167 return MappingOfRange{ 168 MappingSpace: ms, 169 AddrRange: hostarch.AddrRange{ 170 Start: start, 171 End: start + hostarch.Addr(subsetRange.Length()), 172 }, 173 Writable: writable, 174 } 175 } 176 177 // AddMapping adds the given mapping and returns the set of MappableRanges that 178 // previously had no mappings. 179 // 180 // Preconditions: Same as Mappable.AddMapping. 181 func (s *MappingSet) AddMapping(ms MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) []MappableRange { 182 mr := MappableRange{offset, offset + uint64(ar.Length())} 183 var mapped []MappableRange 184 seg, gap := s.Find(mr.Start) 185 for { 186 switch { 187 case seg.Ok() && seg.Start() < mr.End: 188 seg = s.Isolate(seg, mr) 189 seg.Value()[subsetMapping(mr, seg.Range(), ms, ar.Start, writable)] = struct{}{} 190 seg, gap = seg.NextNonEmpty() 191 192 case gap.Ok() && gap.Start() < mr.End: 193 gapMR := gap.Range().Intersect(mr) 194 mapped = append(mapped, gapMR) 195 // Insert a set and continue from the above case. 196 seg, gap = s.Insert(gap, gapMR, make(MappingsOfRange)), MappingGapIterator{} 197 198 default: 199 return mapped 200 } 201 } 202 } 203 204 // RemoveMapping removes the given mapping and returns the set of 205 // MappableRanges that now have no mappings. 206 // 207 // Preconditions: Same as Mappable.RemoveMapping. 208 func (s *MappingSet) RemoveMapping(ms MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) []MappableRange { 209 mr := MappableRange{offset, offset + uint64(ar.Length())} 210 var unmapped []MappableRange 211 212 seg := s.FindSegment(mr.Start) 213 if !seg.Ok() { 214 panic(fmt.Sprintf("MappingSet.RemoveMapping(%v): no segment containing %#x: %v", mr, mr.Start, s)) 215 } 216 for seg.Ok() && seg.Start() < mr.End { 217 // Ensure this segment is limited to our range. 218 seg = s.Isolate(seg, mr) 219 220 // Remove this part of the mapping. 221 mappings := seg.Value() 222 delete(mappings, subsetMapping(mr, seg.Range(), ms, ar.Start, writable)) 223 224 if len(mappings) == 0 { 225 unmapped = append(unmapped, seg.Range()) 226 seg = s.Remove(seg).NextSegment() 227 } else { 228 seg = seg.NextSegment() 229 } 230 } 231 s.MergeAdjacent(mr) 232 return unmapped 233 } 234 235 // Invalidate calls MappingSpace.Invalidate for all mappings of offsets in mr. 236 func (s *MappingSet) Invalidate(mr MappableRange, opts InvalidateOpts) { 237 for seg := s.LowerBoundSegment(mr.Start); seg.Ok() && seg.Start() < mr.End; seg = seg.NextSegment() { 238 segMR := seg.Range() 239 for m := range seg.Value() { 240 region := subsetMapping(segMR, segMR.Intersect(mr), m.MappingSpace, m.AddrRange.Start, m.Writable) 241 region.invalidate(opts) 242 } 243 } 244 } 245 246 // InvalidateAll calls MappingSpace.Invalidate for all mappings of s. 247 func (s *MappingSet) InvalidateAll(opts InvalidateOpts) { 248 for seg := s.FirstSegment(); seg.Ok(); seg = seg.NextSegment() { 249 for m := range seg.Value() { 250 m.invalidate(opts) 251 } 252 } 253 }