123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- package devices
- import (
- "fmt"
- "os"
- "strconv"
- )
- const (
- Wildcard = -1
- )
- type Device struct {
- Rule
- // Path to the device.
- Path string `json:"path"`
- // FileMode permission bits for the device.
- FileMode os.FileMode `json:"file_mode"`
- // Uid of the device.
- Uid uint32 `json:"uid"`
- // Gid of the device.
- Gid uint32 `json:"gid"`
- }
- // Permissions is a cgroupv1-style string to represent device access. It
- // has to be a string for backward compatibility reasons, hence why it has
- // methods to do set operations.
- type Permissions string
- const (
- deviceRead uint = (1 << iota)
- deviceWrite
- deviceMknod
- )
- func (p Permissions) toSet() uint {
- var set uint
- for _, perm := range p {
- switch perm {
- case 'r':
- set |= deviceRead
- case 'w':
- set |= deviceWrite
- case 'm':
- set |= deviceMknod
- }
- }
- return set
- }
- func fromSet(set uint) Permissions {
- var perm string
- if set&deviceRead == deviceRead {
- perm += "r"
- }
- if set&deviceWrite == deviceWrite {
- perm += "w"
- }
- if set&deviceMknod == deviceMknod {
- perm += "m"
- }
- return Permissions(perm)
- }
- // Union returns the union of the two sets of Permissions.
- func (p Permissions) Union(o Permissions) Permissions {
- lhs := p.toSet()
- rhs := o.toSet()
- return fromSet(lhs | rhs)
- }
- // Difference returns the set difference of the two sets of Permissions.
- // In set notation, A.Difference(B) gives you A\B.
- func (p Permissions) Difference(o Permissions) Permissions {
- lhs := p.toSet()
- rhs := o.toSet()
- return fromSet(lhs &^ rhs)
- }
- // Intersection computes the intersection of the two sets of Permissions.
- func (p Permissions) Intersection(o Permissions) Permissions {
- lhs := p.toSet()
- rhs := o.toSet()
- return fromSet(lhs & rhs)
- }
- // IsEmpty returns whether the set of permissions in a Permissions is
- // empty.
- func (p Permissions) IsEmpty() bool {
- return p == Permissions("")
- }
- // IsValid returns whether the set of permissions is a subset of valid
- // permissions (namely, {r,w,m}).
- func (p Permissions) IsValid() bool {
- return p == fromSet(p.toSet())
- }
- type Type rune
- const (
- WildcardDevice Type = 'a'
- BlockDevice Type = 'b'
- CharDevice Type = 'c' // or 'u'
- FifoDevice Type = 'p'
- )
- func (t Type) IsValid() bool {
- switch t {
- case WildcardDevice, BlockDevice, CharDevice, FifoDevice:
- return true
- default:
- return false
- }
- }
- func (t Type) CanMknod() bool {
- switch t {
- case BlockDevice, CharDevice, FifoDevice:
- return true
- default:
- return false
- }
- }
- func (t Type) CanCgroup() bool {
- switch t {
- case WildcardDevice, BlockDevice, CharDevice:
- return true
- default:
- return false
- }
- }
- type Rule struct {
- // Type of device ('c' for char, 'b' for block). If set to 'a', this rule
- // acts as a wildcard and all fields other than Allow are ignored.
- Type Type `json:"type"`
- // Major is the device's major number.
- Major int64 `json:"major"`
- // Minor is the device's minor number.
- Minor int64 `json:"minor"`
- // Permissions is the set of permissions that this rule applies to (in the
- // cgroupv1 format -- any combination of "rwm").
- Permissions Permissions `json:"permissions"`
- // Allow specifies whether this rule is allowed.
- Allow bool `json:"allow"`
- }
- func (d *Rule) CgroupString() string {
- var (
- major = strconv.FormatInt(d.Major, 10)
- minor = strconv.FormatInt(d.Minor, 10)
- )
- if d.Major == Wildcard {
- major = "*"
- }
- if d.Minor == Wildcard {
- minor = "*"
- }
- return fmt.Sprintf("%c %s:%s %s", d.Type, major, minor, d.Permissions)
- }
- func (d *Rule) Mkdev() (uint64, error) {
- return mkDev(d)
- }
|