github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/hostarch/access_type.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 hostarch 16 17 import "golang.org/x/sys/unix" 18 19 // AccessType specifies memory access types. This is used for 20 // setting mapping permissions, as well as communicating faults. 21 // 22 // +stateify savable 23 type AccessType struct { 24 // Read is read access. 25 Read bool 26 27 // Write is write access. 28 Write bool 29 30 // Execute is executable access. 31 Execute bool 32 } 33 34 // String returns a pretty representation of access. This looks like the 35 // familiar r-x, rw-, etc. and can be relied on as such. 36 func (a AccessType) String() string { 37 bits := [3]byte{'-', '-', '-'} 38 if a.Read { 39 bits[0] = 'r' 40 } 41 if a.Write { 42 bits[1] = 'w' 43 } 44 if a.Execute { 45 bits[2] = 'x' 46 } 47 return string(bits[:]) 48 } 49 50 // Any returns true iff at least one of Read, Write or Execute is true. 51 func (a AccessType) Any() bool { 52 return a.Read || a.Write || a.Execute 53 } 54 55 // Prot returns the system prot (unix.PROT_READ, etc.) for this access. 56 func (a AccessType) Prot() int { 57 var prot int 58 if a.Read { 59 prot |= unix.PROT_READ 60 } 61 if a.Write { 62 prot |= unix.PROT_WRITE 63 } 64 if a.Execute { 65 prot |= unix.PROT_EXEC 66 } 67 return prot 68 } 69 70 // SupersetOf returns true iff the access types in a are a superset of the 71 // access types in other. 72 func (a AccessType) SupersetOf(other AccessType) bool { 73 if !a.Read && other.Read { 74 return false 75 } 76 if !a.Write && other.Write { 77 return false 78 } 79 if !a.Execute && other.Execute { 80 return false 81 } 82 return true 83 } 84 85 // Intersect returns the access types set in both a and other. 86 func (a AccessType) Intersect(other AccessType) AccessType { 87 return AccessType{ 88 Read: a.Read && other.Read, 89 Write: a.Write && other.Write, 90 Execute: a.Execute && other.Execute, 91 } 92 } 93 94 // Union returns the access types set in either a or other. 95 func (a AccessType) Union(other AccessType) AccessType { 96 return AccessType{ 97 Read: a.Read || other.Read, 98 Write: a.Write || other.Write, 99 Execute: a.Execute || other.Execute, 100 } 101 } 102 103 // Effective returns the set of effective access types allowed by a, even if 104 // some types are not explicitly allowed. 105 func (a AccessType) Effective() AccessType { 106 // In Linux, Write and Execute access generally imply Read access. See 107 // mm/mmap.c:protection_map. 108 // 109 // The notable exception is get_user_pages, which only checks against 110 // the original vma flags. That said, most user memory accesses do not 111 // use GUP. 112 if a.Write || a.Execute { 113 a.Read = true 114 } 115 return a 116 } 117 118 // Convenient access types. 119 var ( 120 NoAccess = AccessType{} 121 Read = AccessType{Read: true} 122 Write = AccessType{Write: true} 123 Execute = AccessType{Execute: true} 124 ReadWrite = AccessType{Read: true, Write: true} 125 ReadExecute = AccessType{Read: true, Execute: true} 126 AnyAccess = AccessType{Read: true, Write: true, Execute: true} 127 )