github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/platform/kvm/virtual_map.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 kvm 16 17 import ( 18 "bufio" 19 "fmt" 20 "io" 21 "os" 22 "regexp" 23 "strconv" 24 25 "github.com/nicocha30/gvisor-ligolo/pkg/hostarch" 26 ) 27 28 type virtualRegion struct { 29 region 30 accessType hostarch.AccessType 31 shared bool 32 offset uintptr 33 filename string 34 } 35 36 // mapsLine matches a single line from /proc/PID/maps. 37 var mapsLine = regexp.MustCompile("([0-9a-f]+)-([0-9a-f]+) ([r-][w-][x-][sp]) ([0-9a-f]+) [0-9a-f]{2,3}:[0-9a-f]{2,} [0-9]+\\s+(.*)") 38 39 // excludeRegion returns true if these regions should be excluded from the 40 // physical map. Virtual regions need to be excluded if get_user_pages will 41 // fail on those addresses, preventing KVM from satisfying EPT faults. 42 // 43 // This is called by the physical map functions, not applyVirtualRegions. 44 func excludeVirtualRegion(r virtualRegion) bool { 45 return false 46 } 47 48 // applyVirtualRegions parses the process maps file. 49 // 50 // Unlike mappedRegions, these are not consistent over time. 51 func applyVirtualRegions(fn func(vr virtualRegion)) error { 52 // Open /proc/self/maps. 53 f, err := os.Open("/proc/self/maps") 54 if err != nil { 55 return err 56 } 57 defer f.Close() 58 59 // Parse all entries. 60 r := bufio.NewReader(f) 61 for { 62 b, err := r.ReadBytes('\n') 63 if b != nil && len(b) > 0 { 64 m := mapsLine.FindSubmatch(b) 65 if m == nil { 66 // This should not happen: kernel bug? 67 return fmt.Errorf("badly formed line: %v", string(b)) 68 } 69 start, err := strconv.ParseUint(string(m[1]), 16, 64) 70 if err != nil { 71 return fmt.Errorf("bad start address: %v", string(b)) 72 } 73 end, err := strconv.ParseUint(string(m[2]), 16, 64) 74 if err != nil { 75 return fmt.Errorf("bad end address: %v", string(b)) 76 } 77 read := m[3][0] == 'r' 78 write := m[3][1] == 'w' 79 execute := m[3][2] == 'x' 80 shared := m[3][3] == 's' 81 offset, err := strconv.ParseUint(string(m[4]), 16, 64) 82 if err != nil { 83 return fmt.Errorf("bad offset: %v", string(b)) 84 } 85 fn(virtualRegion{ 86 region: region{ 87 virtual: uintptr(start), 88 length: uintptr(end - start), 89 }, 90 accessType: hostarch.AccessType{ 91 Read: read, 92 Write: write, 93 Execute: execute, 94 }, 95 shared: shared, 96 offset: uintptr(offset), 97 filename: string(m[5]), 98 }) 99 } 100 if err != nil && err == io.EOF { 101 break 102 } else if err != nil { 103 return err 104 } 105 } 106 107 return nil 108 }