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