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