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  }