xref: /aosp_15_r20/external/libcap/cap/flags.go (revision 2810ac1b38eead2603277920c78344c84ddf3aff)
1*2810ac1bSKiyoung Kimpackage cap
2*2810ac1bSKiyoung Kim
3*2810ac1bSKiyoung Kimimport "errors"
4*2810ac1bSKiyoung Kim
5*2810ac1bSKiyoung Kim// GetFlag determines if the requested Value is enabled in the
6*2810ac1bSKiyoung Kim// specified Flag of the capability Set.
7*2810ac1bSKiyoung Kimfunc (c *Set) GetFlag(vec Flag, val Value) (bool, error) {
8*2810ac1bSKiyoung Kim	if err := c.good(); err != nil {
9*2810ac1bSKiyoung Kim		// Checked this first, because otherwise we are sure
10*2810ac1bSKiyoung Kim		// cInit has been called.
11*2810ac1bSKiyoung Kim		return false, err
12*2810ac1bSKiyoung Kim	}
13*2810ac1bSKiyoung Kim	offset, mask, err := bitOf(vec, val)
14*2810ac1bSKiyoung Kim	if err != nil {
15*2810ac1bSKiyoung Kim		return false, err
16*2810ac1bSKiyoung Kim	}
17*2810ac1bSKiyoung Kim	c.mu.RLock()
18*2810ac1bSKiyoung Kim	defer c.mu.RUnlock()
19*2810ac1bSKiyoung Kim	return c.flat[offset][vec]&mask != 0, nil
20*2810ac1bSKiyoung Kim}
21*2810ac1bSKiyoung Kim
22*2810ac1bSKiyoung Kim// SetFlag sets the requested bits to the indicated enable state. This
23*2810ac1bSKiyoung Kim// function does not perform any security checks, so values can be set
24*2810ac1bSKiyoung Kim// out-of-order. Only when the Set is used to SetProc() etc., will the
25*2810ac1bSKiyoung Kim// bits be checked for validity and permission by the kernel. If the
26*2810ac1bSKiyoung Kim// function returns an error, the Set will not be modified.
27*2810ac1bSKiyoung Kimfunc (c *Set) SetFlag(vec Flag, enable bool, val ...Value) error {
28*2810ac1bSKiyoung Kim	if err := c.good(); err != nil {
29*2810ac1bSKiyoung Kim		// Checked this first, because otherwise we are sure
30*2810ac1bSKiyoung Kim		// cInit has been called.
31*2810ac1bSKiyoung Kim		return err
32*2810ac1bSKiyoung Kim	}
33*2810ac1bSKiyoung Kim	c.mu.Lock()
34*2810ac1bSKiyoung Kim	defer c.mu.Unlock()
35*2810ac1bSKiyoung Kim	// Make a backup.
36*2810ac1bSKiyoung Kim	replace := make([]uint32, words)
37*2810ac1bSKiyoung Kim	for i := range replace {
38*2810ac1bSKiyoung Kim		replace[i] = c.flat[i][vec]
39*2810ac1bSKiyoung Kim	}
40*2810ac1bSKiyoung Kim	var err error
41*2810ac1bSKiyoung Kim	for _, v := range val {
42*2810ac1bSKiyoung Kim		offset, mask, err2 := bitOf(vec, v)
43*2810ac1bSKiyoung Kim		if err2 != nil {
44*2810ac1bSKiyoung Kim			err = err2
45*2810ac1bSKiyoung Kim			break
46*2810ac1bSKiyoung Kim		}
47*2810ac1bSKiyoung Kim		if enable {
48*2810ac1bSKiyoung Kim			c.flat[offset][vec] |= mask
49*2810ac1bSKiyoung Kim		} else {
50*2810ac1bSKiyoung Kim			c.flat[offset][vec] &= ^mask
51*2810ac1bSKiyoung Kim		}
52*2810ac1bSKiyoung Kim	}
53*2810ac1bSKiyoung Kim	if err == nil {
54*2810ac1bSKiyoung Kim		return nil
55*2810ac1bSKiyoung Kim	}
56*2810ac1bSKiyoung Kim	// Clean up.
57*2810ac1bSKiyoung Kim	for i, bits := range replace {
58*2810ac1bSKiyoung Kim		c.flat[i][vec] = bits
59*2810ac1bSKiyoung Kim	}
60*2810ac1bSKiyoung Kim	return err
61*2810ac1bSKiyoung Kim}
62*2810ac1bSKiyoung Kim
63*2810ac1bSKiyoung Kim// Clear fully clears a capability set.
64*2810ac1bSKiyoung Kimfunc (c *Set) Clear() error {
65*2810ac1bSKiyoung Kim	if err := c.good(); err != nil {
66*2810ac1bSKiyoung Kim		return err
67*2810ac1bSKiyoung Kim	}
68*2810ac1bSKiyoung Kim	// startUp.Do(cInit) is not called here because c cannot be
69*2810ac1bSKiyoung Kim	// initialized except via this package and doing that will
70*2810ac1bSKiyoung Kim	// perform that call at least once (sic).
71*2810ac1bSKiyoung Kim	c.mu.Lock()
72*2810ac1bSKiyoung Kim	defer c.mu.Unlock()
73*2810ac1bSKiyoung Kim	c.flat = make([]data, words)
74*2810ac1bSKiyoung Kim	c.nsRoot = 0
75*2810ac1bSKiyoung Kim	return nil
76*2810ac1bSKiyoung Kim}
77*2810ac1bSKiyoung Kim
78*2810ac1bSKiyoung Kim// FillFlag copies the from flag values of ref into the to flag of
79*2810ac1bSKiyoung Kim// c. With this function, you can raise all of the permitted values in
80*2810ac1bSKiyoung Kim// the c Set from those in ref with c.Fill(cap.Permitted, ref,
81*2810ac1bSKiyoung Kim// cap.Permitted).
82*2810ac1bSKiyoung Kimfunc (c *Set) FillFlag(to Flag, ref *Set, from Flag) error {
83*2810ac1bSKiyoung Kim	if err := c.good(); err != nil {
84*2810ac1bSKiyoung Kim		return err
85*2810ac1bSKiyoung Kim	}
86*2810ac1bSKiyoung Kim	if err := ref.good(); err != nil {
87*2810ac1bSKiyoung Kim		return err
88*2810ac1bSKiyoung Kim	}
89*2810ac1bSKiyoung Kim	if to > Inheritable || from > Inheritable {
90*2810ac1bSKiyoung Kim		return ErrBadValue
91*2810ac1bSKiyoung Kim	}
92*2810ac1bSKiyoung Kim
93*2810ac1bSKiyoung Kim	// Avoid deadlock by using a copy.
94*2810ac1bSKiyoung Kim	if c != ref {
95*2810ac1bSKiyoung Kim		var err error
96*2810ac1bSKiyoung Kim		ref, err = ref.Dup()
97*2810ac1bSKiyoung Kim		if err != nil {
98*2810ac1bSKiyoung Kim			return err
99*2810ac1bSKiyoung Kim		}
100*2810ac1bSKiyoung Kim	}
101*2810ac1bSKiyoung Kim
102*2810ac1bSKiyoung Kim	c.mu.Lock()
103*2810ac1bSKiyoung Kim	defer c.mu.Unlock()
104*2810ac1bSKiyoung Kim	for i := range c.flat {
105*2810ac1bSKiyoung Kim		c.flat[i][to] = ref.flat[i][from]
106*2810ac1bSKiyoung Kim	}
107*2810ac1bSKiyoung Kim	return nil
108*2810ac1bSKiyoung Kim}
109*2810ac1bSKiyoung Kim
110*2810ac1bSKiyoung Kim// Fill copies the from flag values into the to flag. With this
111*2810ac1bSKiyoung Kim// function, you can raise all of the permitted values in the
112*2810ac1bSKiyoung Kim// effective flag with c.Fill(cap.Effective, cap.Permitted).
113*2810ac1bSKiyoung Kimfunc (c *Set) Fill(to, from Flag) error {
114*2810ac1bSKiyoung Kim	return c.FillFlag(to, c, from)
115*2810ac1bSKiyoung Kim}
116*2810ac1bSKiyoung Kim
117*2810ac1bSKiyoung Kim// ErrBadValue indicates a bad capability value was specified.
118*2810ac1bSKiyoung Kimvar ErrBadValue = errors.New("bad capability value")
119*2810ac1bSKiyoung Kim
120*2810ac1bSKiyoung Kim// bitOf converts from a Value into the offset and mask for a specific
121*2810ac1bSKiyoung Kim// Value bit in the compressed (kernel ABI) representation of a
122*2810ac1bSKiyoung Kim// capabilities. If the requested bit is unsupported, an error is
123*2810ac1bSKiyoung Kim// returned.
124*2810ac1bSKiyoung Kimfunc bitOf(vec Flag, val Value) (uint, uint32, error) {
125*2810ac1bSKiyoung Kim	if vec > Inheritable || val > Value(words*32) {
126*2810ac1bSKiyoung Kim		return 0, 0, ErrBadValue
127*2810ac1bSKiyoung Kim	}
128*2810ac1bSKiyoung Kim	u := uint(val)
129*2810ac1bSKiyoung Kim	return u / 32, uint32(1) << (u % 32), nil
130*2810ac1bSKiyoung Kim}
131*2810ac1bSKiyoung Kim
132*2810ac1bSKiyoung Kim// allMask returns the mask of valid bits in the all mask for index.
133*2810ac1bSKiyoung Kimfunc allMask(index uint) (mask uint32) {
134*2810ac1bSKiyoung Kim	if maxValues == 0 {
135*2810ac1bSKiyoung Kim		panic("uninitialized package")
136*2810ac1bSKiyoung Kim	}
137*2810ac1bSKiyoung Kim	base := 32 * uint(index)
138*2810ac1bSKiyoung Kim	if maxValues <= base {
139*2810ac1bSKiyoung Kim		return
140*2810ac1bSKiyoung Kim	}
141*2810ac1bSKiyoung Kim	if maxValues >= 32+base {
142*2810ac1bSKiyoung Kim		mask = ^mask
143*2810ac1bSKiyoung Kim		return
144*2810ac1bSKiyoung Kim	}
145*2810ac1bSKiyoung Kim	mask = uint32((uint64(1) << (maxValues % 32)) - 1)
146*2810ac1bSKiyoung Kim	return
147*2810ac1bSKiyoung Kim}
148*2810ac1bSKiyoung Kim
149*2810ac1bSKiyoung Kim// forceFlag sets 'all' capability values (supported by the kernel) of
150*2810ac1bSKiyoung Kim// a specified Flag to enable.
151*2810ac1bSKiyoung Kimfunc (c *Set) forceFlag(vec Flag, enable bool) error {
152*2810ac1bSKiyoung Kim	if err := c.good(); err != nil {
153*2810ac1bSKiyoung Kim		return err
154*2810ac1bSKiyoung Kim	}
155*2810ac1bSKiyoung Kim	if vec > Inheritable {
156*2810ac1bSKiyoung Kim		return ErrBadSet
157*2810ac1bSKiyoung Kim	}
158*2810ac1bSKiyoung Kim	m := uint32(0)
159*2810ac1bSKiyoung Kim	if enable {
160*2810ac1bSKiyoung Kim		m = ^m
161*2810ac1bSKiyoung Kim	}
162*2810ac1bSKiyoung Kim	c.mu.Lock()
163*2810ac1bSKiyoung Kim	defer c.mu.Unlock()
164*2810ac1bSKiyoung Kim	for i := range c.flat {
165*2810ac1bSKiyoung Kim		c.flat[i][vec] = m & allMask(uint(i))
166*2810ac1bSKiyoung Kim	}
167*2810ac1bSKiyoung Kim	return nil
168*2810ac1bSKiyoung Kim}
169*2810ac1bSKiyoung Kim
170*2810ac1bSKiyoung Kim// ClearFlag clears all the Values associated with the specified Flag.
171*2810ac1bSKiyoung Kimfunc (c *Set) ClearFlag(vec Flag) error {
172*2810ac1bSKiyoung Kim	return c.forceFlag(vec, false)
173*2810ac1bSKiyoung Kim}
174*2810ac1bSKiyoung Kim
175*2810ac1bSKiyoung Kim// Cf returns 0 if c and d are identical. A non-zero Diff value
176*2810ac1bSKiyoung Kim// captures a simple macroscopic summary of how they differ. The
177*2810ac1bSKiyoung Kim// (Diff).Has() function can be used to determine how the two
178*2810ac1bSKiyoung Kim// capability sets differ.
179*2810ac1bSKiyoung Kimfunc (c *Set) Cf(d *Set) (Diff, error) {
180*2810ac1bSKiyoung Kim	if err := c.good(); err != nil {
181*2810ac1bSKiyoung Kim		return 0, err
182*2810ac1bSKiyoung Kim	}
183*2810ac1bSKiyoung Kim	if c == d {
184*2810ac1bSKiyoung Kim		return 0, nil
185*2810ac1bSKiyoung Kim	}
186*2810ac1bSKiyoung Kim	d, err := d.Dup()
187*2810ac1bSKiyoung Kim	if err != nil {
188*2810ac1bSKiyoung Kim		return 0, err
189*2810ac1bSKiyoung Kim	}
190*2810ac1bSKiyoung Kim
191*2810ac1bSKiyoung Kim	c.mu.RLock()
192*2810ac1bSKiyoung Kim	defer c.mu.RUnlock()
193*2810ac1bSKiyoung Kim
194*2810ac1bSKiyoung Kim	var cf Diff
195*2810ac1bSKiyoung Kim	for i := 0; i < words; i++ {
196*2810ac1bSKiyoung Kim		if c.flat[i][Effective]^d.flat[i][Effective] != 0 {
197*2810ac1bSKiyoung Kim			cf |= effectiveDiff
198*2810ac1bSKiyoung Kim		}
199*2810ac1bSKiyoung Kim		if c.flat[i][Permitted]^d.flat[i][Permitted] != 0 {
200*2810ac1bSKiyoung Kim			cf |= permittedDiff
201*2810ac1bSKiyoung Kim		}
202*2810ac1bSKiyoung Kim		if c.flat[i][Inheritable]^d.flat[i][Inheritable] != 0 {
203*2810ac1bSKiyoung Kim			cf |= inheritableDiff
204*2810ac1bSKiyoung Kim		}
205*2810ac1bSKiyoung Kim	}
206*2810ac1bSKiyoung Kim	return cf, nil
207*2810ac1bSKiyoung Kim}
208*2810ac1bSKiyoung Kim
209*2810ac1bSKiyoung Kim// Compare returns 0 if c and d are identical in content.
210*2810ac1bSKiyoung Kim//
211*2810ac1bSKiyoung Kim// Deprecated: Replace with (*Set).Cf().
212*2810ac1bSKiyoung Kim//
213*2810ac1bSKiyoung Kim// Example, replace this:
214*2810ac1bSKiyoung Kim//
215*2810ac1bSKiyoung Kim//    diff, err := a.Compare(b)
216*2810ac1bSKiyoung Kim//    if err != nil {
217*2810ac1bSKiyoung Kim//      return err
218*2810ac1bSKiyoung Kim//    }
219*2810ac1bSKiyoung Kim//    if diff == 0 {
220*2810ac1bSKiyoung Kim//      return nil
221*2810ac1bSKiyoung Kim//    }
222*2810ac1bSKiyoung Kim//    if diff & (1 << Effective) {
223*2810ac1bSKiyoung Kim//      log.Print("a and b difference includes Effective values")
224*2810ac1bSKiyoung Kim//    }
225*2810ac1bSKiyoung Kim//
226*2810ac1bSKiyoung Kim// with this:
227*2810ac1bSKiyoung Kim//
228*2810ac1bSKiyoung Kim//    diff, err := a.Cf(b)
229*2810ac1bSKiyoung Kim//    if err != nil {
230*2810ac1bSKiyoung Kim//      return err
231*2810ac1bSKiyoung Kim//    }
232*2810ac1bSKiyoung Kim//    if diff == 0 {
233*2810ac1bSKiyoung Kim//      return nil
234*2810ac1bSKiyoung Kim//    }
235*2810ac1bSKiyoung Kim//    if diff.Has(Effective) {
236*2810ac1bSKiyoung Kim//      log.Print("a and b difference includes Effective values")
237*2810ac1bSKiyoung Kim//    }
238*2810ac1bSKiyoung Kimfunc (c *Set) Compare(d *Set) (uint, error) {
239*2810ac1bSKiyoung Kim	u, err := c.Cf(d)
240*2810ac1bSKiyoung Kim	return uint(u), err
241*2810ac1bSKiyoung Kim}
242*2810ac1bSKiyoung Kim
243*2810ac1bSKiyoung Kim// Differs processes the result of Compare and determines if the
244*2810ac1bSKiyoung Kim// Flag's components were different.
245*2810ac1bSKiyoung Kim//
246*2810ac1bSKiyoung Kim// Deprecated: Replace with (Diff).Has().
247*2810ac1bSKiyoung Kim//
248*2810ac1bSKiyoung Kim// Example, replace this:
249*2810ac1bSKiyoung Kim//
250*2810ac1bSKiyoung Kim//    diff, err := a.Compare(b)
251*2810ac1bSKiyoung Kim//    ...
252*2810ac1bSKiyoung Kim//    if diff & (1 << Effective) {
253*2810ac1bSKiyoung Kim//       ... different effective capabilities ...
254*2810ac1bSKiyoung Kim//    }
255*2810ac1bSKiyoung Kim//
256*2810ac1bSKiyoung Kim// with this:
257*2810ac1bSKiyoung Kim//
258*2810ac1bSKiyoung Kim//    diff, err := a.Cf(b)
259*2810ac1bSKiyoung Kim//    ...
260*2810ac1bSKiyoung Kim//    if diff.Has(Effective) {
261*2810ac1bSKiyoung Kim//       ... different effective capabilities ...
262*2810ac1bSKiyoung Kim//    }
263*2810ac1bSKiyoung Kimfunc Differs(cf uint, vec Flag) bool {
264*2810ac1bSKiyoung Kim	return cf&(1<<vec) != 0
265*2810ac1bSKiyoung Kim}
266*2810ac1bSKiyoung Kim
267*2810ac1bSKiyoung Kim// Has processes the Diff result of (*Set).Cf() and determines if the
268*2810ac1bSKiyoung Kim// Flag's components were different in that result.
269*2810ac1bSKiyoung Kimfunc (cf Diff) Has(vec Flag) bool {
270*2810ac1bSKiyoung Kim	return uint(cf)&(1<<vec) != 0
271*2810ac1bSKiyoung Kim}
272