xref: /aosp_15_r20/external/libcap/cap/flags.go (revision 2810ac1b38eead2603277920c78344c84ddf3aff)
1package cap
2
3import "errors"
4
5// GetFlag determines if the requested Value is enabled in the
6// specified Flag of the capability Set.
7func (c *Set) GetFlag(vec Flag, val Value) (bool, error) {
8	if err := c.good(); err != nil {
9		// Checked this first, because otherwise we are sure
10		// cInit has been called.
11		return false, err
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 err := c.good(); err != nil {
29		// Checked this first, because otherwise we are sure
30		// cInit has been called.
31		return err
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 err := c.good(); err != nil {
66		return err
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// FillFlag copies the from flag values of ref into the to flag of
79// c. With this function, you can raise all of the permitted values in
80// the c Set from those in ref with c.Fill(cap.Permitted, ref,
81// cap.Permitted).
82func (c *Set) FillFlag(to Flag, ref *Set, from Flag) error {
83	if err := c.good(); err != nil {
84		return err
85	}
86	if err := ref.good(); err != nil {
87		return err
88	}
89	if to > Inheritable || from > Inheritable {
90		return ErrBadValue
91	}
92
93	// Avoid deadlock by using a copy.
94	if c != ref {
95		var err error
96		ref, err = ref.Dup()
97		if err != nil {
98			return err
99		}
100	}
101
102	c.mu.Lock()
103	defer c.mu.Unlock()
104	for i := range c.flat {
105		c.flat[i][to] = ref.flat[i][from]
106	}
107	return nil
108}
109
110// Fill copies the from flag values into the to flag. With this
111// function, you can raise all of the permitted values in the
112// effective flag with c.Fill(cap.Effective, cap.Permitted).
113func (c *Set) Fill(to, from Flag) error {
114	return c.FillFlag(to, c, from)
115}
116
117// ErrBadValue indicates a bad capability value was specified.
118var ErrBadValue = errors.New("bad capability value")
119
120// bitOf converts from a Value into the offset and mask for a specific
121// Value bit in the compressed (kernel ABI) representation of a
122// capabilities. If the requested bit is unsupported, an error is
123// returned.
124func bitOf(vec Flag, val Value) (uint, uint32, error) {
125	if vec > Inheritable || val > Value(words*32) {
126		return 0, 0, ErrBadValue
127	}
128	u := uint(val)
129	return u / 32, uint32(1) << (u % 32), nil
130}
131
132// allMask returns the mask of valid bits in the all mask for index.
133func allMask(index uint) (mask uint32) {
134	if maxValues == 0 {
135		panic("uninitialized package")
136	}
137	base := 32 * uint(index)
138	if maxValues <= base {
139		return
140	}
141	if maxValues >= 32+base {
142		mask = ^mask
143		return
144	}
145	mask = uint32((uint64(1) << (maxValues % 32)) - 1)
146	return
147}
148
149// forceFlag sets 'all' capability values (supported by the kernel) of
150// a specified Flag to enable.
151func (c *Set) forceFlag(vec Flag, enable bool) error {
152	if err := c.good(); err != nil {
153		return err
154	}
155	if vec > Inheritable {
156		return ErrBadSet
157	}
158	m := uint32(0)
159	if enable {
160		m = ^m
161	}
162	c.mu.Lock()
163	defer c.mu.Unlock()
164	for i := range c.flat {
165		c.flat[i][vec] = m & allMask(uint(i))
166	}
167	return nil
168}
169
170// ClearFlag clears all the Values associated with the specified Flag.
171func (c *Set) ClearFlag(vec Flag) error {
172	return c.forceFlag(vec, false)
173}
174
175// Cf returns 0 if c and d are identical. A non-zero Diff value
176// captures a simple macroscopic summary of how they differ. The
177// (Diff).Has() function can be used to determine how the two
178// capability sets differ.
179func (c *Set) Cf(d *Set) (Diff, error) {
180	if err := c.good(); err != nil {
181		return 0, err
182	}
183	if c == d {
184		return 0, nil
185	}
186	d, err := d.Dup()
187	if err != nil {
188		return 0, err
189	}
190
191	c.mu.RLock()
192	defer c.mu.RUnlock()
193
194	var cf Diff
195	for i := 0; i < words; i++ {
196		if c.flat[i][Effective]^d.flat[i][Effective] != 0 {
197			cf |= effectiveDiff
198		}
199		if c.flat[i][Permitted]^d.flat[i][Permitted] != 0 {
200			cf |= permittedDiff
201		}
202		if c.flat[i][Inheritable]^d.flat[i][Inheritable] != 0 {
203			cf |= inheritableDiff
204		}
205	}
206	return cf, nil
207}
208
209// Compare returns 0 if c and d are identical in content.
210//
211// Deprecated: Replace with (*Set).Cf().
212//
213// Example, replace this:
214//
215//    diff, err := a.Compare(b)
216//    if err != nil {
217//      return err
218//    }
219//    if diff == 0 {
220//      return nil
221//    }
222//    if diff & (1 << Effective) {
223//      log.Print("a and b difference includes Effective values")
224//    }
225//
226// with this:
227//
228//    diff, err := a.Cf(b)
229//    if err != nil {
230//      return err
231//    }
232//    if diff == 0 {
233//      return nil
234//    }
235//    if diff.Has(Effective) {
236//      log.Print("a and b difference includes Effective values")
237//    }
238func (c *Set) Compare(d *Set) (uint, error) {
239	u, err := c.Cf(d)
240	return uint(u), err
241}
242
243// Differs processes the result of Compare and determines if the
244// Flag's components were different.
245//
246// Deprecated: Replace with (Diff).Has().
247//
248// Example, replace this:
249//
250//    diff, err := a.Compare(b)
251//    ...
252//    if diff & (1 << Effective) {
253//       ... different effective capabilities ...
254//    }
255//
256// with this:
257//
258//    diff, err := a.Cf(b)
259//    ...
260//    if diff.Has(Effective) {
261//       ... different effective capabilities ...
262//    }
263func Differs(cf uint, vec Flag) bool {
264	return cf&(1<<vec) != 0
265}
266
267// Has processes the Diff result of (*Set).Cf() and determines if the
268// Flag's components were different in that result.
269func (cf Diff) Has(vec Flag) bool {
270	return uint(cf)&(1<<vec) != 0
271}
272