aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2021-10-22 16:32:51 -0700
committerAndrew G. Morgan <morgan@kernel.org>2021-10-22 16:32:51 -0700
commit687dc0b8fea42dd58a1b6ca8f50b28fe049bb2a7 (patch)
tree43c5b5a5abd96815fd5c46f8f31c52122a34b23b
parent3d60128581126f69e31ee963d47cef456ee9e371 (diff)
downloadlibcap-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.go18
-rw-r--r--cap/file.go4
-rw-r--r--cap/flags.go28
-rw-r--r--cap/iab.go39
-rw-r--r--cap/text.go2
5 files changed, 58 insertions, 33 deletions
diff --git a/cap/cap.go b/cap/cap.go
index 10c24a2..784bf65 100644
--- a/cap/cap.go
+++ b/cap/cap.go
@@ -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
diff --git a/cap/iab.go b/cap/iab.go
index e10687c..9199e57 100644
--- a/cap/iab.go
+++ b/cap/iab.go
@@ -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)