...

Source file src/github.com/opencontainers/runc/libcontainer/devices/device.go

Documentation: github.com/opencontainers/runc/libcontainer/devices

     1  package devices
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strconv"
     7  )
     8  
     9  const (
    10  	Wildcard = -1
    11  )
    12  
    13  type Device struct {
    14  	Rule
    15  
    16  	// Path to the device.
    17  	Path string `json:"path"`
    18  
    19  	// FileMode permission bits for the device.
    20  	FileMode os.FileMode `json:"file_mode"`
    21  
    22  	// Uid of the device.
    23  	Uid uint32 `json:"uid"`
    24  
    25  	// Gid of the device.
    26  	Gid uint32 `json:"gid"`
    27  }
    28  
    29  // Permissions is a cgroupv1-style string to represent device access. It
    30  // has to be a string for backward compatibility reasons, hence why it has
    31  // methods to do set operations.
    32  type Permissions string
    33  
    34  const (
    35  	deviceRead uint = (1 << iota)
    36  	deviceWrite
    37  	deviceMknod
    38  )
    39  
    40  func (p Permissions) toSet() uint {
    41  	var set uint
    42  	for _, perm := range p {
    43  		switch perm {
    44  		case 'r':
    45  			set |= deviceRead
    46  		case 'w':
    47  			set |= deviceWrite
    48  		case 'm':
    49  			set |= deviceMknod
    50  		}
    51  	}
    52  	return set
    53  }
    54  
    55  func fromSet(set uint) Permissions {
    56  	var perm string
    57  	if set&deviceRead == deviceRead {
    58  		perm += "r"
    59  	}
    60  	if set&deviceWrite == deviceWrite {
    61  		perm += "w"
    62  	}
    63  	if set&deviceMknod == deviceMknod {
    64  		perm += "m"
    65  	}
    66  	return Permissions(perm)
    67  }
    68  
    69  // Union returns the union of the two sets of Permissions.
    70  func (p Permissions) Union(o Permissions) Permissions {
    71  	lhs := p.toSet()
    72  	rhs := o.toSet()
    73  	return fromSet(lhs | rhs)
    74  }
    75  
    76  // Difference returns the set difference of the two sets of Permissions.
    77  // In set notation, A.Difference(B) gives you A\B.
    78  func (p Permissions) Difference(o Permissions) Permissions {
    79  	lhs := p.toSet()
    80  	rhs := o.toSet()
    81  	return fromSet(lhs &^ rhs)
    82  }
    83  
    84  // Intersection computes the intersection of the two sets of Permissions.
    85  func (p Permissions) Intersection(o Permissions) Permissions {
    86  	lhs := p.toSet()
    87  	rhs := o.toSet()
    88  	return fromSet(lhs & rhs)
    89  }
    90  
    91  // IsEmpty returns whether the set of permissions in a Permissions is
    92  // empty.
    93  func (p Permissions) IsEmpty() bool {
    94  	return p == Permissions("")
    95  }
    96  
    97  // IsValid returns whether the set of permissions is a subset of valid
    98  // permissions (namely, {r,w,m}).
    99  func (p Permissions) IsValid() bool {
   100  	return p == fromSet(p.toSet())
   101  }
   102  
   103  type Type rune
   104  
   105  const (
   106  	WildcardDevice Type = 'a'
   107  	BlockDevice    Type = 'b'
   108  	CharDevice     Type = 'c' // or 'u'
   109  	FifoDevice     Type = 'p'
   110  )
   111  
   112  func (t Type) IsValid() bool {
   113  	switch t {
   114  	case WildcardDevice, BlockDevice, CharDevice, FifoDevice:
   115  		return true
   116  	default:
   117  		return false
   118  	}
   119  }
   120  
   121  func (t Type) CanMknod() bool {
   122  	switch t {
   123  	case BlockDevice, CharDevice, FifoDevice:
   124  		return true
   125  	default:
   126  		return false
   127  	}
   128  }
   129  
   130  func (t Type) CanCgroup() bool {
   131  	switch t {
   132  	case WildcardDevice, BlockDevice, CharDevice:
   133  		return true
   134  	default:
   135  		return false
   136  	}
   137  }
   138  
   139  type Rule struct {
   140  	// Type of device ('c' for char, 'b' for block). If set to 'a', this rule
   141  	// acts as a wildcard and all fields other than Allow are ignored.
   142  	Type Type `json:"type"`
   143  
   144  	// Major is the device's major number.
   145  	Major int64 `json:"major"`
   146  
   147  	// Minor is the device's minor number.
   148  	Minor int64 `json:"minor"`
   149  
   150  	// Permissions is the set of permissions that this rule applies to (in the
   151  	// cgroupv1 format -- any combination of "rwm").
   152  	Permissions Permissions `json:"permissions"`
   153  
   154  	// Allow specifies whether this rule is allowed.
   155  	Allow bool `json:"allow"`
   156  }
   157  
   158  func (d *Rule) CgroupString() string {
   159  	var (
   160  		major = strconv.FormatInt(d.Major, 10)
   161  		minor = strconv.FormatInt(d.Minor, 10)
   162  	)
   163  	if d.Major == Wildcard {
   164  		major = "*"
   165  	}
   166  	if d.Minor == Wildcard {
   167  		minor = "*"
   168  	}
   169  	return fmt.Sprintf("%c %s:%s %s", d.Type, major, minor, d.Permissions)
   170  }
   171  
   172  func (d *Rule) Mkdev() (uint64, error) {
   173  	return mkDev(d)
   174  }
   175  

View as plain text