diff options
author | Andrew G. Morgan <morgan@kernel.org> | 2021-10-22 16:32:51 -0700 |
---|---|---|
committer | Andrew G. Morgan <morgan@kernel.org> | 2021-10-22 16:32:51 -0700 |
commit | 687dc0b8fea42dd58a1b6ca8f50b28fe049bb2a7 (patch) | |
tree | 43c5b5a5abd96815fd5c46f8f31c52122a34b23b | |
parent | 3d60128581126f69e31ee963d47cef456ee9e371 (diff) | |
download | libcap-687dc0b8fea42dd58a1b6ca8f50b28fe049bb2a7.tar.gz |
Unify the cap package tests for good *Set or *IAB types.
We had somewhat inconsistent checks before, so this should cut
down on corner cases to worry about.
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r-- | cap/cap.go | 18 | ||||
-rw-r--r-- | cap/file.go | 4 | ||||
-rw-r--r-- | cap/flags.go | 28 | ||||
-rw-r--r-- | cap/iab.go | 39 | ||||
-rw-r--r-- | cap/text.go | 2 |
5 files changed, 58 insertions, 33 deletions
@@ -318,10 +318,18 @@ func NewSet() *Set { // request of the Set is invalid in some way. var ErrBadSet = errors.New("bad capability set") +// good confirms that c looks valid. +func (c *Set) good() error { + if c == nil || len(c.flat) == 0 { + return ErrBadSet + } + return nil +} + // Dup returns a copy of the specified capability set. func (c *Set) Dup() (*Set, error) { - if c == nil || len(c.flat) == 0 { - return nil, ErrBadSet + if err := c.good(); err != nil { + return nil, err } n := NewSet() c.mu.RLock() @@ -355,9 +363,6 @@ func GetProc() *Set { // setProc uses syscaller to set process capabilities. Note, c is // either private to or (read) locked by the caller. func (sc *syscaller) setProc(c *Set) error { - if c == nil || len(c.flat) == 0 { - return ErrBadSet - } return sc.capwcall(syscall.SYS_CAPSET, &header{magic: magic}, c.flat) } @@ -371,6 +376,9 @@ func (sc *syscaller) setProc(c *Set) error { // function as part of a (*Launcher).Launch(), the call only sets the // capabilities of the thread being used to perform the launch. func (c *Set) SetProc() error { + if err := c.good(); err != nil { + return err + } state, sc := scwStateSC() defer scwSetState(launchBlocked, state, -1) c.mu.RLock() diff --git a/cap/file.go b/cap/file.go index b433c9b..9a5b10c 100644 --- a/cap/file.go +++ b/cap/file.go @@ -369,8 +369,8 @@ var MinExtFlagSize = uint(8) // Note, Export() generates exported byte streams that are importable // by libcap.cap_copy_int() as well as Import(). func (c *Set) Export() ([]byte, error) { - if c == nil { - return nil, ErrBadSet + if err := c.good(); err != nil { + return nil, err } if MinExtFlagSize > 255 { return nil, ErrOutOfRange diff --git a/cap/flags.go b/cap/flags.go index 0463484..c4c2ed8 100644 --- a/cap/flags.go +++ b/cap/flags.go @@ -5,10 +5,10 @@ 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 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 @@ -80,8 +80,11 @@ func (c *Set) Clear() error { // 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 c == nil || len(c.flat) == 0 || ref == nil || len(ref.flat) == 0 { - return ErrBadSet + if err := c.good(); err != nil { + return err + } + if err := ref.good(); err != nil { + return err } if to > Inheritable || from > Inheritable { return ErrBadValue @@ -146,7 +149,10 @@ func allMask(index uint) (mask uint32) { // 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 c == nil || len(c.flat) == 0 || vec > Inheritable { + if err := c.good(); err != nil { + return err + } + if vec > Inheritable { return ErrBadSet } m := uint32(0) @@ -171,8 +177,8 @@ func (c *Set) ClearFlag(vec Flag) error { // (Diff).Has() function can be used to determine how the two // capability sets differ. func (c *Set) Cf(d *Set) (Diff, error) { - if c == nil || len(c.flat) == 0 || d == nil || len(d.flat) == 0 { - return 0, ErrBadSet + if err := c.good(); err != nil { + return 0, err } if c == d { return 0, nil @@ -81,10 +81,18 @@ func NewIAB() *IAB { } } +// good confirms the iab looks to be initialized. +func (iab *IAB) good() error { + if iab == nil || len(iab.i) == 0 || len(iab.i) != words || len(iab.a) != words || len(iab.nb) != words { + return ErrBadValue + } + return nil +} + // Dup returns a duplicate copy of the IAB. func (iab *IAB) Dup() (*IAB, error) { - if iab == nil { - return nil, ErrBadValue + if err := iab.good(); err != nil { + return nil, err } v := NewIAB() iab.mu.RLock() @@ -173,7 +181,7 @@ func IABFromText(text string) (*IAB, error) { // String serializes an IAB to a string format. func (iab *IAB) String() string { - if iab == nil { + if err := iab.good(); err != nil { return "<invalid>" } var vs []string @@ -254,8 +262,8 @@ func (sc *syscaller) iabSetProc(iab *IAB) (err error) { // other bits, so this function carefully performs the the combined // operation in the most flexible manner. func (iab *IAB) SetProc() error { - if iab == nil { - return ErrBadValue + if err := iab.good(); err != nil { + return err } state, sc := scwStateSC() defer scwSetState(launchBlocked, state, -1) @@ -267,7 +275,10 @@ func (iab *IAB) SetProc() error { // GetVector returns the raised state of the specific capability bit // of the indicated vector. func (iab *IAB) GetVector(vec Vector, val Value) (bool, error) { - if val >= MaxBits() || iab == nil { + if err := iab.good(); err != nil { + return false, err + } + if val >= MaxBits() { return false, ErrBadValue } iab.mu.RLock() @@ -293,8 +304,8 @@ func (iab *IAB) GetVector(vec Vector, val Value) (bool, error) { // equivalent to lowering the Bounding vector of the process (when // successfully applied with (*IAB).SetProc()). func (iab *IAB) SetVector(vec Vector, raised bool, vals ...Value) error { - if iab == nil { - return ErrBadValue + if err := iab.good(); err != nil { + return err } iab.mu.Lock() defer iab.mu.Unlock() @@ -338,8 +349,8 @@ func (iab *IAB) SetVector(vec Vector, raised bool, vals ...Value) error { // the bits are inverted from what you might expect - that is lowered // bits from the Set will be raised in the Bound vector. func (iab *IAB) Fill(vec Vector, c *Set, flag Flag) error { - if iab == nil { - return ErrBadValue + if err := iab.good(); err != nil { + return err } // work with a copy to avoid potential deadlock. s, err := c.Dup() @@ -370,16 +381,16 @@ func (iab *IAB) Fill(vec Vector, c *Set, flag Flag) error { // tuples are considered identical. The macroscopic differences can be // investigated with (IABDiff).Has(). func (iab *IAB) Cf(alt *IAB) (IABDiff, error) { + if err := iab.good(); err != nil { + return 0, err + } if iab == alt { return 0, nil } - if iab == nil || alt == nil || len(iab.i) != words || len(alt.i) != words || len(iab.a) != words || len(alt.a) != words || len(iab.nb) != words || len(alt.nb) != words { - return 0, ErrBadValue - } // Avoid holding two locks at once. ref, err := alt.Dup() if err != nil { - return 0, ErrBadValue + return 0, err } iab.mu.RLock() defer iab.mu.RUnlock() diff --git a/cap/text.go b/cap/text.go index 7c3f540..42cb7fc 100644 --- a/cap/text.go +++ b/cap/text.go @@ -85,7 +85,7 @@ func (c *Set) histo(bins []int, patterns []uint, from, limit Value) uint { // any given release. Further, it will always be an inverse of // cap.FromText(). func (c *Set) String() string { - if c == nil || len(c.flat) == 0 { + if err := c.good(); err != nil { return "<invalid>" } bins := make([]int, 8) |