diff options
Diffstat (limited to 'cap/flags.go')
-rw-r--r-- | cap/flags.go | 160 |
1 files changed, 126 insertions, 34 deletions
diff --git a/cap/flags.go b/cap/flags.go index 83a871a..c4c2ed8 100644 --- a/cap/flags.go +++ b/cap/flags.go @@ -2,13 +2,13 @@ package cap import "errors" -// GetFlag determines if the requested bit is enabled in the Flag -// vector of the capability Set. +// 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 c == nil || len(c.flat) == 0 { + if err := c.good(); err != nil { // Checked this first, because otherwise we are sure // cInit has been called. - return false, ErrBadSet + return false, err } offset, mask, err := bitOf(vec, val) if err != nil { @@ -25,10 +25,10 @@ func (c *Set) GetFlag(vec Flag, val Value) (bool, error) { // 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 c == nil || len(c.flat) == 0 { + if err := c.good(); err != nil { // Checked this first, because otherwise we are sure // cInit has been called. - return ErrBadSet + return err } c.mu.Lock() defer c.mu.Unlock() @@ -62,8 +62,8 @@ func (c *Set) SetFlag(vec Flag, enable bool, val ...Value) error { // Clear fully clears a capability set. func (c *Set) Clear() error { - if c == nil || len(c.flat) == 0 { - return ErrBadSet + 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 @@ -75,31 +75,52 @@ func (c *Set) Clear() error { 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 { - if c == nil || len(c.flat) == 0 { - return ErrBadSet +// 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] = c.flat[i][from] + 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 capability vector. If the requested bit is unsupported, an error -// is returned. +// 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 @@ -126,9 +147,12 @@ func allMask(index uint) (mask uint32) { } // forceFlag sets 'all' capability values (supported by the kernel) of -// a flag vector to enable. +// a specified Flag to enable. func (c *Set) forceFlag(vec Flag, enable bool) error { - if c == nil || len(c.flat) == 0 || vec > Inheritable { + if err := c.good(); err != nil { + return err + } + if vec > Inheritable { return ErrBadSet } m := uint32(0) @@ -143,37 +167,105 @@ func (c *Set) forceFlag(vec Flag, enable bool) error { return nil } -// ClearFlag clears a specific vector of Values associated with the -// specified Flag. +// ClearFlag clears all the Values associated with the specified Flag. func (c *Set) ClearFlag(vec Flag) error { return c.forceFlag(vec, false) } -// Compare returns 0 if c and d are identical in content. Otherwise, -// this function returns a non-zero value of 3 independent bits: -// (differE ? 1:0) | (differP ? 2:0) | (differI ? 4:0). The Differs() -// function can be used to test for a difference in a specific Flag. -func (c *Set) Compare(d *Set) (uint, error) { - if c == nil || len(c.flat) == 0 || d == nil || len(d.flat) == 0 { - return 0, ErrBadSet +// 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 } - var cf uint + 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 |= (1 << Effective) + cf |= effectiveDiff } if c.flat[i][Permitted]^d.flat[i][Permitted] != 0 { - cf |= (1 << Permitted) + cf |= permittedDiff } if c.flat[i][Inheritable]^d.flat[i][Inheritable] != 0 { - cf |= (1 << Inheritable) + 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 +} |