• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1package cap
2
3import "errors"
4
5// GetFlag determines if the requested bit is enabled in the Flag
6// vector of the capability Set.
7func (c *Set) GetFlag(vec Flag, val Value) (bool, error) {
8	if c == nil || len(c.flat) == 0 {
9		// Checked this first, because otherwise we are sure
10		// cInit has been called.
11		return false, ErrBadSet
12	}
13	offset, mask, err := bitOf(vec, val)
14	if err != nil {
15		return false, err
16	}
17	c.mu.RLock()
18	defer c.mu.RUnlock()
19	return c.flat[offset][vec]&mask != 0, nil
20}
21
22// SetFlag sets the requested bits to the indicated enable state. This
23// function does not perform any security checks, so values can be set
24// out-of-order. Only when the Set is used to SetProc() etc., will the
25// bits be checked for validity and permission by the kernel. If the
26// function returns an error, the Set will not be modified.
27func (c *Set) SetFlag(vec Flag, enable bool, val ...Value) error {
28	if c == nil || len(c.flat) == 0 {
29		// Checked this first, because otherwise we are sure
30		// cInit has been called.
31		return ErrBadSet
32	}
33	c.mu.Lock()
34	defer c.mu.Unlock()
35	// Make a backup.
36	replace := make([]uint32, words)
37	for i := range replace {
38		replace[i] = c.flat[i][vec]
39	}
40	var err error
41	for _, v := range val {
42		offset, mask, err2 := bitOf(vec, v)
43		if err2 != nil {
44			err = err2
45			break
46		}
47		if enable {
48			c.flat[offset][vec] |= mask
49		} else {
50			c.flat[offset][vec] &= ^mask
51		}
52	}
53	if err == nil {
54		return nil
55	}
56	// Clean up.
57	for i, bits := range replace {
58		c.flat[i][vec] = bits
59	}
60	return err
61}
62
63// Clear fully clears a capability set.
64func (c *Set) Clear() error {
65	if c == nil || len(c.flat) == 0 {
66		return ErrBadSet
67	}
68	// startUp.Do(cInit) is not called here because c cannot be
69	// initialized except via this package and doing that will
70	// perform that call at least once (sic).
71	c.mu.Lock()
72	defer c.mu.Unlock()
73	c.flat = make([]data, words)
74	c.nsRoot = 0
75	return nil
76}
77
78// ErrBadValue indicates a bad capability value was specified.
79var ErrBadValue = errors.New("bad capability value")
80
81// bitOf converts from a Value into the offset and mask for a
82// specific Value bit in the compressed (kernel ABI) representation of
83// a capability vector. If the requested bit is unsupported, an error
84// is returned.
85func bitOf(vec Flag, val Value) (uint, uint32, error) {
86	if vec > Inheritable || val > Value(words*32) {
87		return 0, 0, ErrBadValue
88	}
89	u := uint(val)
90	return u / 32, uint32(1) << (u % 32), nil
91}
92
93// allMask returns the mask of valid bits in the all mask for index.
94func allMask(index uint) (mask uint32) {
95	if maxValues == 0 {
96		panic("uninitialized package")
97	}
98	base := 32 * uint(index)
99	if maxValues <= base {
100		return
101	}
102	if maxValues >= 32+base {
103		mask = ^mask
104		return
105	}
106	mask = uint32((uint64(1) << (maxValues % 32)) - 1)
107	return
108}
109
110// forceFlag sets 'all' capability values (supported by the kernel) of
111// a flag vector to enable.
112func (c *Set) forceFlag(vec Flag, enable bool) error {
113	if c == nil || len(c.flat) == 0 || vec > Inheritable {
114		return ErrBadSet
115	}
116	m := uint32(0)
117	if enable {
118		m = ^m
119	}
120	c.mu.Lock()
121	defer c.mu.Unlock()
122	for i := range c.flat {
123		c.flat[i][vec] = m & allMask(uint(i))
124	}
125	return nil
126}
127
128// ClearFlag clears a specific vector of Values associated with the
129// specified Flag.
130func (c *Set) ClearFlag(vec Flag) error {
131	return c.forceFlag(vec, false)
132}
133
134// Compare returns 0 if c and d are identical in content. Otherwise,
135// this function returns a non-zero value of 3 independent bits:
136// (differE ? 1:0) | (differP ? 2:0) | (differI ? 4:0). The Differs()
137// function can be used to test for a difference in a specific Flag.
138func (c *Set) Compare(d *Set) (uint, error) {
139	if c == nil || len(c.flat) == 0 || d == nil || len(d.flat) == 0 {
140		return 0, ErrBadSet
141	}
142	var cf uint
143	for i := 0; i < words; i++ {
144		if c.flat[i][Effective]^d.flat[i][Effective] != 0 {
145			cf |= (1 << Effective)
146		}
147		if c.flat[i][Permitted]^d.flat[i][Permitted] != 0 {
148			cf |= (1 << Permitted)
149		}
150		if c.flat[i][Inheritable]^d.flat[i][Inheritable] != 0 {
151			cf |= (1 << Inheritable)
152		}
153	}
154	return cf, nil
155}
156
157// Differs processes the result of Compare and determines if the
158// Flag's components were different.
159func Differs(cf uint, vec Flag) bool {
160	return cf&(1<<vec) != 0
161}
162