272 lines
6.3 KiB
Go
272 lines
6.3 KiB
Go
package cap
|
|
|
|
import "errors"
|
|
|
|
// GetFlag determines if the requested Value is enabled in the
|
|
// specified Flag of the capability Set.
|
|
func (c *Set) GetFlag(vec Flag, val Value) (bool, error) {
|
|
if err := c.good(); err != nil {
|
|
// Checked this first, because otherwise we are sure
|
|
// cInit has been called.
|
|
return false, err
|
|
}
|
|
offset, mask, err := bitOf(vec, val)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.flat[offset][vec]&mask != 0, nil
|
|
}
|
|
|
|
// SetFlag sets the requested bits to the indicated enable state. This
|
|
// function does not perform any security checks, so values can be set
|
|
// out-of-order. Only when the Set is used to SetProc() etc., will the
|
|
// bits be checked for validity and permission by the kernel. If the
|
|
// function returns an error, the Set will not be modified.
|
|
func (c *Set) SetFlag(vec Flag, enable bool, val ...Value) error {
|
|
if err := c.good(); err != nil {
|
|
// Checked this first, because otherwise we are sure
|
|
// cInit has been called.
|
|
return err
|
|
}
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
// Make a backup.
|
|
replace := make([]uint32, words)
|
|
for i := range replace {
|
|
replace[i] = c.flat[i][vec]
|
|
}
|
|
var err error
|
|
for _, v := range val {
|
|
offset, mask, err2 := bitOf(vec, v)
|
|
if err2 != nil {
|
|
err = err2
|
|
break
|
|
}
|
|
if enable {
|
|
c.flat[offset][vec] |= mask
|
|
} else {
|
|
c.flat[offset][vec] &= ^mask
|
|
}
|
|
}
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
// Clean up.
|
|
for i, bits := range replace {
|
|
c.flat[i][vec] = bits
|
|
}
|
|
return err
|
|
}
|
|
|
|
// Clear fully clears a capability set.
|
|
func (c *Set) Clear() error {
|
|
if err := c.good(); err != nil {
|
|
return err
|
|
}
|
|
// startUp.Do(cInit) is not called here because c cannot be
|
|
// initialized except via this package and doing that will
|
|
// perform that call at least once (sic).
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.flat = make([]data, words)
|
|
c.nsRoot = 0
|
|
return nil
|
|
}
|
|
|
|
// FillFlag copies the from flag values of ref into the to flag of
|
|
// c. With this function, you can raise all of the permitted values in
|
|
// the c Set from those in ref with c.Fill(cap.Permitted, ref,
|
|
// cap.Permitted).
|
|
func (c *Set) FillFlag(to Flag, ref *Set, from Flag) error {
|
|
if err := c.good(); err != nil {
|
|
return err
|
|
}
|
|
if err := ref.good(); err != nil {
|
|
return err
|
|
}
|
|
if to > Inheritable || from > Inheritable {
|
|
return ErrBadValue
|
|
}
|
|
|
|
// Avoid deadlock by using a copy.
|
|
if c != ref {
|
|
var err error
|
|
ref, err = ref.Dup()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
for i := range c.flat {
|
|
c.flat[i][to] = ref.flat[i][from]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Fill copies the from flag values into the to flag. With this
|
|
// function, you can raise all of the permitted values in the
|
|
// effective flag with c.Fill(cap.Effective, cap.Permitted).
|
|
func (c *Set) Fill(to, from Flag) error {
|
|
return c.FillFlag(to, c, from)
|
|
}
|
|
|
|
// ErrBadValue indicates a bad capability value was specified.
|
|
var ErrBadValue = errors.New("bad capability value")
|
|
|
|
// bitOf converts from a Value into the offset and mask for a specific
|
|
// Value bit in the compressed (kernel ABI) representation of a
|
|
// capabilities. If the requested bit is unsupported, an error is
|
|
// returned.
|
|
func bitOf(vec Flag, val Value) (uint, uint32, error) {
|
|
if vec > Inheritable || val > Value(words*32) {
|
|
return 0, 0, ErrBadValue
|
|
}
|
|
u := uint(val)
|
|
return u / 32, uint32(1) << (u % 32), nil
|
|
}
|
|
|
|
// allMask returns the mask of valid bits in the all mask for index.
|
|
func allMask(index uint) (mask uint32) {
|
|
if maxValues == 0 {
|
|
panic("uninitialized package")
|
|
}
|
|
base := 32 * uint(index)
|
|
if maxValues <= base {
|
|
return
|
|
}
|
|
if maxValues >= 32+base {
|
|
mask = ^mask
|
|
return
|
|
}
|
|
mask = uint32((uint64(1) << (maxValues % 32)) - 1)
|
|
return
|
|
}
|
|
|
|
// forceFlag sets 'all' capability values (supported by the kernel) of
|
|
// a specified Flag to enable.
|
|
func (c *Set) forceFlag(vec Flag, enable bool) error {
|
|
if err := c.good(); err != nil {
|
|
return err
|
|
}
|
|
if vec > Inheritable {
|
|
return ErrBadSet
|
|
}
|
|
m := uint32(0)
|
|
if enable {
|
|
m = ^m
|
|
}
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
for i := range c.flat {
|
|
c.flat[i][vec] = m & allMask(uint(i))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ClearFlag clears all the Values associated with the specified Flag.
|
|
func (c *Set) ClearFlag(vec Flag) error {
|
|
return c.forceFlag(vec, false)
|
|
}
|
|
|
|
// Cf returns 0 if c and d are identical. A non-zero Diff value
|
|
// captures a simple macroscopic summary of how they differ. The
|
|
// (Diff).Has() function can be used to determine how the two
|
|
// capability sets differ.
|
|
func (c *Set) Cf(d *Set) (Diff, error) {
|
|
if err := c.good(); err != nil {
|
|
return 0, err
|
|
}
|
|
if c == d {
|
|
return 0, nil
|
|
}
|
|
d, err := d.Dup()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
var cf Diff
|
|
for i := 0; i < words; i++ {
|
|
if c.flat[i][Effective]^d.flat[i][Effective] != 0 {
|
|
cf |= effectiveDiff
|
|
}
|
|
if c.flat[i][Permitted]^d.flat[i][Permitted] != 0 {
|
|
cf |= permittedDiff
|
|
}
|
|
if c.flat[i][Inheritable]^d.flat[i][Inheritable] != 0 {
|
|
cf |= inheritableDiff
|
|
}
|
|
}
|
|
return cf, nil
|
|
}
|
|
|
|
// Compare returns 0 if c and d are identical in content.
|
|
//
|
|
// Deprecated: Replace with (*Set).Cf().
|
|
//
|
|
// Example, replace this:
|
|
//
|
|
// diff, err := a.Compare(b)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
// if diff == 0 {
|
|
// return nil
|
|
// }
|
|
// if diff & (1 << Effective) {
|
|
// log.Print("a and b difference includes Effective values")
|
|
// }
|
|
//
|
|
// with this:
|
|
//
|
|
// diff, err := a.Cf(b)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
// if diff == 0 {
|
|
// return nil
|
|
// }
|
|
// if diff.Has(Effective) {
|
|
// log.Print("a and b difference includes Effective values")
|
|
// }
|
|
func (c *Set) Compare(d *Set) (uint, error) {
|
|
u, err := c.Cf(d)
|
|
return uint(u), err
|
|
}
|
|
|
|
// Differs processes the result of Compare and determines if the
|
|
// Flag's components were different.
|
|
//
|
|
// Deprecated: Replace with (Diff).Has().
|
|
//
|
|
// Example, replace this:
|
|
//
|
|
// diff, err := a.Compare(b)
|
|
// ...
|
|
// if diff & (1 << Effective) {
|
|
// ... different effective capabilities ...
|
|
// }
|
|
//
|
|
// with this:
|
|
//
|
|
// diff, err := a.Cf(b)
|
|
// ...
|
|
// if diff.Has(Effective) {
|
|
// ... different effective capabilities ...
|
|
// }
|
|
func Differs(cf uint, vec Flag) bool {
|
|
return cf&(1<<vec) != 0
|
|
}
|
|
|
|
// Has processes the Diff result of (*Set).Cf() and determines if the
|
|
// Flag's components were different in that result.
|
|
func (cf Diff) Has(vec Flag) bool {
|
|
return uint(cf)&(1<<vec) != 0
|
|
}
|