gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/platform/kvm/kvm_safecopy_test.go (about) 1 // Copyright 2021 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 // FIXME(gvisor.dev/issue/6629): These tests don't pass on ARM64. 16 // 17 //go:build amd64 18 // +build amd64 19 20 package kvm 21 22 import ( 23 "fmt" 24 "os" 25 "testing" 26 "unsafe" 27 28 "golang.org/x/sys/unix" 29 "gvisor.dev/gvisor/pkg/hostarch" 30 "gvisor.dev/gvisor/pkg/memutil" 31 "gvisor.dev/gvisor/pkg/safecopy" 32 ) 33 34 func testSafecopy(t *testing.T, mapSize uintptr, fileSize uintptr, testFunc func(t *testing.T, c *vCPU, addr uintptr)) { 35 memfd, err := memutil.CreateMemFD(fmt.Sprintf("kvm_test_%d", os.Getpid()), 0) 36 if err != nil { 37 t.Errorf("error creating memfd: %v", err) 38 } 39 40 memfile := os.NewFile(uintptr(memfd), "kvm_test") 41 memfile.Truncate(int64(fileSize)) 42 kvmTest(t, nil, func(c *vCPU) bool { 43 const n = 10 44 mappings := make([]uintptr, n) 45 defer func() { 46 for i := 0; i < n && mappings[i] != 0; i++ { 47 unix.RawSyscall( 48 unix.SYS_MUNMAP, 49 mappings[i], mapSize, 0) 50 } 51 }() 52 for i := 0; i < n; i++ { 53 addr, _, errno := unix.RawSyscall6( 54 unix.SYS_MMAP, 55 0, 56 mapSize, 57 unix.PROT_READ|unix.PROT_WRITE, 58 unix.MAP_SHARED|unix.MAP_FILE, 59 uintptr(memfile.Fd()), 60 0) 61 if errno != 0 { 62 t.Errorf("error mapping file: %v", errno) 63 } 64 mappings[i] = addr 65 testFunc(t, c, addr) 66 } 67 return false 68 }) 69 } 70 71 func TestSafecopySigbus(t *testing.T) { 72 mapSize := uintptr(faultBlockSize) 73 fileSize := mapSize - hostarch.PageSize 74 buf := make([]byte, hostarch.PageSize) 75 testSafecopy(t, mapSize, fileSize, func(t *testing.T, c *vCPU, addr uintptr) { 76 want := safecopy.BusError{addr + fileSize} 77 bluepill(c) 78 _, err := safecopy.CopyIn(buf, unsafe.Pointer(addr+fileSize)) 79 if err != want { 80 t.Errorf("expected error: got %v, want %v", err, want) 81 } 82 }) 83 } 84 85 func TestSafecopy(t *testing.T) { 86 mapSize := uintptr(faultBlockSize) 87 fileSize := mapSize 88 testSafecopy(t, mapSize, fileSize, func(t *testing.T, c *vCPU, addr uintptr) { 89 want := uint32(0x12345678) 90 bluepill(c) 91 _, err := safecopy.SwapUint32(unsafe.Pointer(addr+fileSize-8), want) 92 if err != nil { 93 t.Errorf("unexpected error: %v", err) 94 } 95 bluepill(c) 96 val, err := safecopy.LoadUint32(unsafe.Pointer(addr + fileSize - 8)) 97 if err != nil { 98 t.Errorf("unexpected error: %v", err) 99 } 100 if val != want { 101 t.Errorf("incorrect value: got %x, want %x", val, want) 102 } 103 }) 104 }