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  )