gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/memmap/mapping_set_test.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 "slices" 19 "testing" 20 21 "gvisor.dev/gvisor/pkg/hostarch" 22 ) 23 24 type testMappingSpace struct { 25 // Ideally we'd store the full ranges that were invalidated, rather 26 // than individual calls to Invalidate, as they are an implementation 27 // detail, but this is the simplest way for now. 28 inv []hostarch.AddrRange 29 } 30 31 func (n *testMappingSpace) reset() { 32 n.inv = []hostarch.AddrRange{} 33 } 34 35 func (n *testMappingSpace) Invalidate(ar hostarch.AddrRange, opts InvalidateOpts) { 36 n.inv = append(n.inv, ar) 37 } 38 39 func TestAddRemoveMapping(t *testing.T) { 40 set := MappingSet{} 41 ms := &testMappingSpace{} 42 43 mapped := set.AddMapping(ms, hostarch.AddrRange{0x10000, 0x12000}, 0x1000, true) 44 if got, want := mapped, []MappableRange{{0x1000, 0x3000}}; !slices.Equal(got, want) { 45 t.Errorf("AddMapping: got %+v, wanted %+v", got, want) 46 } 47 48 // Mappings (hostarch.AddrRanges => memmap.MappableRange): 49 // [0x10000, 0x12000) => [0x1000, 0x3000) 50 t.Log(&set) 51 52 mapped = set.AddMapping(ms, hostarch.AddrRange{0x20000, 0x21000}, 0x2000, true) 53 if len(mapped) != 0 { 54 t.Errorf("AddMapping: got %+v, wanted []", mapped) 55 } 56 57 // Mappings: 58 // [0x10000, 0x11000) => [0x1000, 0x2000) 59 // [0x11000, 0x12000) and [0x20000, 0x21000) => [0x2000, 0x3000) 60 t.Log(&set) 61 62 mapped = set.AddMapping(ms, hostarch.AddrRange{0x30000, 0x31000}, 0x4000, true) 63 if got, want := mapped, []MappableRange{{0x4000, 0x5000}}; !slices.Equal(got, want) { 64 t.Errorf("AddMapping: got %+v, wanted %+v", got, want) 65 } 66 67 // Mappings: 68 // [0x10000, 0x11000) => [0x1000, 0x2000) 69 // [0x11000, 0x12000) and [0x20000, 0x21000) => [0x2000, 0x3000) 70 // [0x30000, 0x31000) => [0x4000, 0x5000) 71 t.Log(&set) 72 73 mapped = set.AddMapping(ms, hostarch.AddrRange{0x12000, 0x15000}, 0x3000, true) 74 if got, want := mapped, []MappableRange{{0x3000, 0x4000}, {0x5000, 0x6000}}; !slices.Equal(got, want) { 75 t.Errorf("AddMapping: got %+v, wanted %+v", got, want) 76 } 77 78 // Mappings: 79 // [0x10000, 0x11000) => [0x1000, 0x2000) 80 // [0x11000, 0x12000) and [0x20000, 0x21000) => [0x2000, 0x3000) 81 // [0x12000, 0x13000) => [0x3000, 0x4000) 82 // [0x13000, 0x14000) and [0x30000, 0x31000) => [0x4000, 0x5000) 83 // [0x14000, 0x15000) => [0x5000, 0x6000) 84 t.Log(&set) 85 86 unmapped := set.RemoveMapping(ms, hostarch.AddrRange{0x10000, 0x11000}, 0x1000, true) 87 if got, want := unmapped, []MappableRange{{0x1000, 0x2000}}; !slices.Equal(got, want) { 88 t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want) 89 } 90 91 // Mappings: 92 // [0x11000, 0x12000) and [0x20000, 0x21000) => [0x2000, 0x3000) 93 // [0x12000, 0x13000) => [0x3000, 0x4000) 94 // [0x13000, 0x14000) and [0x30000, 0x31000) => [0x4000, 0x5000) 95 // [0x14000, 0x15000) => [0x5000, 0x6000) 96 t.Log(&set) 97 98 unmapped = set.RemoveMapping(ms, hostarch.AddrRange{0x20000, 0x21000}, 0x2000, true) 99 if len(unmapped) != 0 { 100 t.Errorf("RemoveMapping: got %+v, wanted []", unmapped) 101 } 102 103 // Mappings: 104 // [0x11000, 0x13000) => [0x2000, 0x4000) 105 // [0x13000, 0x14000) and [0x30000, 0x31000) => [0x4000, 0x5000) 106 // [0x14000, 0x15000) => [0x5000, 0x6000) 107 t.Log(&set) 108 109 unmapped = set.RemoveMapping(ms, hostarch.AddrRange{0x11000, 0x15000}, 0x2000, true) 110 if got, want := unmapped, []MappableRange{{0x2000, 0x4000}, {0x5000, 0x6000}}; !slices.Equal(got, want) { 111 t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want) 112 } 113 114 // Mappings: 115 // [0x30000, 0x31000) => [0x4000, 0x5000) 116 t.Log(&set) 117 118 unmapped = set.RemoveMapping(ms, hostarch.AddrRange{0x30000, 0x31000}, 0x4000, true) 119 if got, want := unmapped, []MappableRange{{0x4000, 0x5000}}; !slices.Equal(got, want) { 120 t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want) 121 } 122 } 123 124 func TestInvalidateWholeMapping(t *testing.T) { 125 set := MappingSet{} 126 ms := &testMappingSpace{} 127 128 set.AddMapping(ms, hostarch.AddrRange{0x10000, 0x11000}, 0, true) 129 // Mappings: 130 // [0x10000, 0x11000) => [0, 0x1000) 131 t.Log(&set) 132 set.Invalidate(MappableRange{0, 0x1000}, InvalidateOpts{}) 133 if got, want := ms.inv, []hostarch.AddrRange{{Start: 0x10000, End: 0x11000}}; !slices.Equal(got, want) { 134 t.Errorf("Invalidate: got %+v, wanted %+v", got, want) 135 } 136 } 137 138 func TestInvalidatePartialMapping(t *testing.T) { 139 set := MappingSet{} 140 ms := &testMappingSpace{} 141 142 set.AddMapping(ms, hostarch.AddrRange{0x10000, 0x13000}, 0, true) 143 // Mappings: 144 // [0x10000, 0x13000) => [0, 0x3000) 145 t.Log(&set) 146 set.Invalidate(MappableRange{0x1000, 0x2000}, InvalidateOpts{}) 147 if got, want := ms.inv, []hostarch.AddrRange{{Start: 0x11000, End: 0x12000}}; !slices.Equal(got, want) { 148 t.Errorf("Invalidate: got %+v, wanted %+v", got, want) 149 } 150 } 151 152 func TestInvalidateMultipleMappings(t *testing.T) { 153 set := MappingSet{} 154 ms := &testMappingSpace{} 155 156 set.AddMapping(ms, hostarch.AddrRange{0x10000, 0x11000}, 0, true) 157 set.AddMapping(ms, hostarch.AddrRange{0x20000, 0x21000}, 0x2000, true) 158 // Mappings: 159 // [0x10000, 0x11000) => [0, 0x1000) 160 // [0x12000, 0x13000) => [0x2000, 0x3000) 161 t.Log(&set) 162 set.Invalidate(MappableRange{0, 0x3000}, InvalidateOpts{}) 163 if got, want := ms.inv, []hostarch.AddrRange{{Start: 0x10000, End: 0x11000}, {Start: 0x20000, End: 0x21000}}; !slices.Equal(got, want) { 164 t.Errorf("Invalidate: got %+v, wanted %+v", got, want) 165 } 166 } 167 168 func TestInvalidateOverlappingMappings(t *testing.T) { 169 set := MappingSet{} 170 ms1 := &testMappingSpace{} 171 ms2 := &testMappingSpace{} 172 173 set.AddMapping(ms1, hostarch.AddrRange{0x10000, 0x12000}, 0, true) 174 set.AddMapping(ms2, hostarch.AddrRange{0x20000, 0x22000}, 0x1000, true) 175 // Mappings: 176 // ms1:[0x10000, 0x12000) => [0, 0x2000) 177 // ms2:[0x11000, 0x13000) => [0x1000, 0x3000) 178 t.Log(&set) 179 set.Invalidate(MappableRange{0x1000, 0x2000}, InvalidateOpts{}) 180 if got, want := ms1.inv, []hostarch.AddrRange{{Start: 0x11000, End: 0x12000}}; !slices.Equal(got, want) { 181 t.Errorf("Invalidate: ms1: got %+v, wanted %+v", got, want) 182 } 183 if got, want := ms2.inv, []hostarch.AddrRange{{Start: 0x20000, End: 0x21000}}; !slices.Equal(got, want) { 184 t.Errorf("Invalidate: ms1: got %+v, wanted %+v", got, want) 185 } 186 } 187 188 func TestMixedWritableMappings(t *testing.T) { 189 set := MappingSet{} 190 ms := &testMappingSpace{} 191 192 mapped := set.AddMapping(ms, hostarch.AddrRange{0x10000, 0x12000}, 0x1000, true) 193 if got, want := mapped, []MappableRange{{0x1000, 0x3000}}; !slices.Equal(got, want) { 194 t.Errorf("AddMapping: got %+v, wanted %+v", got, want) 195 } 196 197 // Mappings: 198 // [0x10000, 0x12000) writable => [0x1000, 0x3000) 199 t.Log(&set) 200 201 mapped = set.AddMapping(ms, hostarch.AddrRange{0x20000, 0x22000}, 0x2000, false) 202 if got, want := mapped, []MappableRange{{0x3000, 0x4000}}; !slices.Equal(got, want) { 203 t.Errorf("AddMapping: got %+v, wanted %+v", got, want) 204 } 205 206 // Mappings: 207 // [0x10000, 0x11000) writable => [0x1000, 0x2000) 208 // [0x11000, 0x12000) writable and [0x20000, 0x21000) readonly => [0x2000, 0x3000) 209 // [0x21000, 0x22000) readonly => [0x3000, 0x4000) 210 t.Log(&set) 211 212 // Unmap should fail because we specified the readonly map address range, but 213 // asked to unmap a writable segment. 214 unmapped := set.RemoveMapping(ms, hostarch.AddrRange{0x20000, 0x21000}, 0x2000, true) 215 if len(unmapped) != 0 { 216 t.Errorf("RemoveMapping: got %+v, wanted []", unmapped) 217 } 218 219 // Readonly mapping removed, but writable mapping still exists in the range, 220 // so no mappable range fully unmapped. 221 unmapped = set.RemoveMapping(ms, hostarch.AddrRange{0x20000, 0x21000}, 0x2000, false) 222 if len(unmapped) != 0 { 223 t.Errorf("RemoveMapping: got %+v, wanted []", unmapped) 224 } 225 226 // Mappings: 227 // [0x10000, 0x12000) writable => [0x1000, 0x3000) 228 // [0x21000, 0x22000) readonly => [0x3000, 0x4000) 229 t.Log(&set) 230 231 unmapped = set.RemoveMapping(ms, hostarch.AddrRange{0x11000, 0x12000}, 0x2000, true) 232 if got, want := unmapped, []MappableRange{{0x2000, 0x3000}}; !slices.Equal(got, want) { 233 t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want) 234 } 235 236 // Mappings: 237 // [0x10000, 0x12000) writable => [0x1000, 0x3000) 238 // [0x21000, 0x22000) readonly => [0x3000, 0x4000) 239 t.Log(&set) 240 241 // Unmap should fail since writable bit doesn't match. 242 unmapped = set.RemoveMapping(ms, hostarch.AddrRange{0x10000, 0x12000}, 0x1000, false) 243 if len(unmapped) != 0 { 244 t.Errorf("RemoveMapping: got %+v, wanted []", unmapped) 245 } 246 247 unmapped = set.RemoveMapping(ms, hostarch.AddrRange{0x10000, 0x12000}, 0x1000, true) 248 if got, want := unmapped, []MappableRange{{0x1000, 0x2000}}; !slices.Equal(got, want) { 249 t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want) 250 } 251 252 // Mappings: 253 // [0x21000, 0x22000) readonly => [0x3000, 0x4000) 254 t.Log(&set) 255 256 unmapped = set.RemoveMapping(ms, hostarch.AddrRange{0x21000, 0x22000}, 0x3000, false) 257 if got, want := unmapped, []MappableRange{{0x3000, 0x4000}}; !slices.Equal(got, want) { 258 t.Errorf("RemoveMapping: got %+v, wanted %+v", got, want) 259 } 260 }