1*2810ac1bSKiyoung Kimpackage cap 2*2810ac1bSKiyoung Kim 3*2810ac1bSKiyoung Kimimport ( 4*2810ac1bSKiyoung Kim "fmt" 5*2810ac1bSKiyoung Kim "io/ioutil" 6*2810ac1bSKiyoung Kim "strconv" 7*2810ac1bSKiyoung Kim "strings" 8*2810ac1bSKiyoung Kim "sync" 9*2810ac1bSKiyoung Kim) 10*2810ac1bSKiyoung Kim 11*2810ac1bSKiyoung Kim// omask returns the offset and mask for a specific capability. 12*2810ac1bSKiyoung Kimfunc omask(c Value) (uint, uint32) { 13*2810ac1bSKiyoung Kim u := uint(c) 14*2810ac1bSKiyoung Kim return u >> 5, uint32(1) << (u & 31) 15*2810ac1bSKiyoung Kim} 16*2810ac1bSKiyoung Kim 17*2810ac1bSKiyoung Kim// IAB holds a summary of all of the inheritable capability vectors: 18*2810ac1bSKiyoung Kim// Inh, Amb and Bound. The Bound vector is the logical inverse (two's 19*2810ac1bSKiyoung Kim// complement) of the process' Bounding set. That is, raising a Value 20*2810ac1bSKiyoung Kim// in the Bound (think blocked) vector is equivalent to dropping that 21*2810ac1bSKiyoung Kim// Value from the process' Bounding set. This convention is used to 22*2810ac1bSKiyoung Kim// support the empty IAB as being mostly harmless. 23*2810ac1bSKiyoung Kimtype IAB struct { 24*2810ac1bSKiyoung Kim mu sync.RWMutex 25*2810ac1bSKiyoung Kim a, i, nb []uint32 26*2810ac1bSKiyoung Kim} 27*2810ac1bSKiyoung Kim 28*2810ac1bSKiyoung Kim// Vector enumerates which of the inheritable IAB capability vectors 29*2810ac1bSKiyoung Kim// is being manipulated. 30*2810ac1bSKiyoung Kimtype Vector uint 31*2810ac1bSKiyoung Kim 32*2810ac1bSKiyoung Kim// Inh, Amb, Bound enumerate the IAB vector components. (Vector) Inh 33*2810ac1bSKiyoung Kim// is equivalent to (Flag) Inheritable. They are named differently for 34*2810ac1bSKiyoung Kim// syntax/type checking reasons. 35*2810ac1bSKiyoung Kimconst ( 36*2810ac1bSKiyoung Kim Inh Vector = iota 37*2810ac1bSKiyoung Kim Amb 38*2810ac1bSKiyoung Kim Bound 39*2810ac1bSKiyoung Kim) 40*2810ac1bSKiyoung Kim 41*2810ac1bSKiyoung Kim// IABDiff holds the non-error result of an (*IAB).Cf() 42*2810ac1bSKiyoung Kim// function call. It can be interpreted with the function 43*2810ac1bSKiyoung Kim// (IABDiff).Has(). 44*2810ac1bSKiyoung Kimtype IABDiff uint 45*2810ac1bSKiyoung Kim 46*2810ac1bSKiyoung Kim// iBits, iBits and bBits track the (semi-)independent parts of an 47*2810ac1bSKiyoung Kim// IABDiff. 48*2810ac1bSKiyoung Kimconst ( 49*2810ac1bSKiyoung Kim iBits IABDiff = 1 << Inh 50*2810ac1bSKiyoung Kim aBits IABDiff = 1 << Amb 51*2810ac1bSKiyoung Kim bBits IABDiff = 1 << Bound 52*2810ac1bSKiyoung Kim) 53*2810ac1bSKiyoung Kim 54*2810ac1bSKiyoung Kim// Has determines if an IAB comparison differs in a specific vector. 55*2810ac1bSKiyoung Kimfunc (d IABDiff) Has(v Vector) bool { 56*2810ac1bSKiyoung Kim return d&(1<<v) != 0 57*2810ac1bSKiyoung Kim} 58*2810ac1bSKiyoung Kim 59*2810ac1bSKiyoung Kim// String identifies a Vector value by its conventional I A or B 60*2810ac1bSKiyoung Kim// string abbreviation. 61*2810ac1bSKiyoung Kimfunc (v Vector) String() string { 62*2810ac1bSKiyoung Kim switch v { 63*2810ac1bSKiyoung Kim case Inh: 64*2810ac1bSKiyoung Kim return "I" 65*2810ac1bSKiyoung Kim case Amb: 66*2810ac1bSKiyoung Kim return "A" 67*2810ac1bSKiyoung Kim case Bound: 68*2810ac1bSKiyoung Kim return "B" 69*2810ac1bSKiyoung Kim default: 70*2810ac1bSKiyoung Kim return "<Error>" 71*2810ac1bSKiyoung Kim } 72*2810ac1bSKiyoung Kim} 73*2810ac1bSKiyoung Kim 74*2810ac1bSKiyoung Kim// NewIAB returns an empty IAB. 75*2810ac1bSKiyoung Kimfunc NewIAB() *IAB { 76*2810ac1bSKiyoung Kim startUp.Do(multisc.cInit) 77*2810ac1bSKiyoung Kim return &IAB{ 78*2810ac1bSKiyoung Kim i: make([]uint32, words), 79*2810ac1bSKiyoung Kim a: make([]uint32, words), 80*2810ac1bSKiyoung Kim nb: make([]uint32, words), 81*2810ac1bSKiyoung Kim } 82*2810ac1bSKiyoung Kim} 83*2810ac1bSKiyoung Kim 84*2810ac1bSKiyoung Kim// good confirms the iab looks to be initialized. 85*2810ac1bSKiyoung Kimfunc (iab *IAB) good() error { 86*2810ac1bSKiyoung Kim if iab == nil || len(iab.i) == 0 || len(iab.i) != words || len(iab.a) != words || len(iab.nb) != words { 87*2810ac1bSKiyoung Kim return ErrBadValue 88*2810ac1bSKiyoung Kim } 89*2810ac1bSKiyoung Kim return nil 90*2810ac1bSKiyoung Kim} 91*2810ac1bSKiyoung Kim 92*2810ac1bSKiyoung Kim// Dup returns a duplicate copy of the IAB. 93*2810ac1bSKiyoung Kimfunc (iab *IAB) Dup() (*IAB, error) { 94*2810ac1bSKiyoung Kim if err := iab.good(); err != nil { 95*2810ac1bSKiyoung Kim return nil, err 96*2810ac1bSKiyoung Kim } 97*2810ac1bSKiyoung Kim v := NewIAB() 98*2810ac1bSKiyoung Kim iab.mu.RLock() 99*2810ac1bSKiyoung Kim defer iab.mu.RUnlock() 100*2810ac1bSKiyoung Kim copy(v.i, iab.i) 101*2810ac1bSKiyoung Kim copy(v.a, iab.a) 102*2810ac1bSKiyoung Kim copy(v.nb, iab.nb) 103*2810ac1bSKiyoung Kim return v, nil 104*2810ac1bSKiyoung Kim} 105*2810ac1bSKiyoung Kim 106*2810ac1bSKiyoung Kim// IABInit allocates a new IAB tuple. 107*2810ac1bSKiyoung Kim// 108*2810ac1bSKiyoung Kim// Deprecated: Replace with NewIAB. 109*2810ac1bSKiyoung Kim// 110*2810ac1bSKiyoung Kim// Example, replace this: 111*2810ac1bSKiyoung Kim// 112*2810ac1bSKiyoung Kim// iab := IABInit() 113*2810ac1bSKiyoung Kim// 114*2810ac1bSKiyoung Kim// with this: 115*2810ac1bSKiyoung Kim// 116*2810ac1bSKiyoung Kim// iab := NewIAB() 117*2810ac1bSKiyoung Kimfunc IABInit() *IAB { 118*2810ac1bSKiyoung Kim return NewIAB() 119*2810ac1bSKiyoung Kim} 120*2810ac1bSKiyoung Kim 121*2810ac1bSKiyoung Kim// IABGetProc summarizes the Inh, Amb and Bound capability vectors of 122*2810ac1bSKiyoung Kim// the current process. 123*2810ac1bSKiyoung Kimfunc IABGetProc() *IAB { 124*2810ac1bSKiyoung Kim iab := NewIAB() 125*2810ac1bSKiyoung Kim current := GetProc() 126*2810ac1bSKiyoung Kim iab.Fill(Inh, current, Inheritable) 127*2810ac1bSKiyoung Kim for c := MaxBits(); c > 0; { 128*2810ac1bSKiyoung Kim c-- 129*2810ac1bSKiyoung Kim offset, mask := omask(c) 130*2810ac1bSKiyoung Kim if a, _ := GetAmbient(c); a { 131*2810ac1bSKiyoung Kim iab.a[offset] |= mask 132*2810ac1bSKiyoung Kim } 133*2810ac1bSKiyoung Kim if b, err := GetBound(c); err == nil && !b { 134*2810ac1bSKiyoung Kim iab.nb[offset] |= mask 135*2810ac1bSKiyoung Kim } 136*2810ac1bSKiyoung Kim } 137*2810ac1bSKiyoung Kim return iab 138*2810ac1bSKiyoung Kim} 139*2810ac1bSKiyoung Kim 140*2810ac1bSKiyoung Kim// IABFromText parses a string representing an IAB, as generated 141*2810ac1bSKiyoung Kim// by IAB.String(), to generate an IAB. 142*2810ac1bSKiyoung Kimfunc IABFromText(text string) (*IAB, error) { 143*2810ac1bSKiyoung Kim iab := NewIAB() 144*2810ac1bSKiyoung Kim if len(text) == 0 { 145*2810ac1bSKiyoung Kim return iab, nil 146*2810ac1bSKiyoung Kim } 147*2810ac1bSKiyoung Kim for _, f := range strings.Split(text, ",") { 148*2810ac1bSKiyoung Kim var i, a, nb bool 149*2810ac1bSKiyoung Kim var j int 150*2810ac1bSKiyoung Kim for j = 0; j < len(f); j++ { 151*2810ac1bSKiyoung Kim switch f[j : j+1] { 152*2810ac1bSKiyoung Kim case "!": 153*2810ac1bSKiyoung Kim nb = true 154*2810ac1bSKiyoung Kim case "^": 155*2810ac1bSKiyoung Kim i = true 156*2810ac1bSKiyoung Kim a = true 157*2810ac1bSKiyoung Kim case "%": 158*2810ac1bSKiyoung Kim i = true 159*2810ac1bSKiyoung Kim default: 160*2810ac1bSKiyoung Kim goto done 161*2810ac1bSKiyoung Kim } 162*2810ac1bSKiyoung Kim } 163*2810ac1bSKiyoung Kim done: 164*2810ac1bSKiyoung Kim c, err := FromName(f[j:]) 165*2810ac1bSKiyoung Kim if err != nil { 166*2810ac1bSKiyoung Kim return nil, err 167*2810ac1bSKiyoung Kim } 168*2810ac1bSKiyoung Kim offset, mask := omask(c) 169*2810ac1bSKiyoung Kim if i || !nb { 170*2810ac1bSKiyoung Kim iab.i[offset] |= mask 171*2810ac1bSKiyoung Kim } 172*2810ac1bSKiyoung Kim if a { 173*2810ac1bSKiyoung Kim iab.a[offset] |= mask 174*2810ac1bSKiyoung Kim } 175*2810ac1bSKiyoung Kim if nb { 176*2810ac1bSKiyoung Kim iab.nb[offset] |= mask 177*2810ac1bSKiyoung Kim } 178*2810ac1bSKiyoung Kim } 179*2810ac1bSKiyoung Kim return iab, nil 180*2810ac1bSKiyoung Kim} 181*2810ac1bSKiyoung Kim 182*2810ac1bSKiyoung Kim// String serializes an IAB to a string format. 183*2810ac1bSKiyoung Kimfunc (iab *IAB) String() string { 184*2810ac1bSKiyoung Kim if err := iab.good(); err != nil { 185*2810ac1bSKiyoung Kim return "<invalid>" 186*2810ac1bSKiyoung Kim } 187*2810ac1bSKiyoung Kim var vs []string 188*2810ac1bSKiyoung Kim iab.mu.RLock() 189*2810ac1bSKiyoung Kim defer iab.mu.RUnlock() 190*2810ac1bSKiyoung Kim for c := Value(0); c < Value(maxValues); c++ { 191*2810ac1bSKiyoung Kim offset, mask := omask(c) 192*2810ac1bSKiyoung Kim i := (iab.i[offset] & mask) != 0 193*2810ac1bSKiyoung Kim a := (iab.a[offset] & mask) != 0 194*2810ac1bSKiyoung Kim nb := (iab.nb[offset] & mask) != 0 195*2810ac1bSKiyoung Kim var cs []string 196*2810ac1bSKiyoung Kim if nb { 197*2810ac1bSKiyoung Kim cs = append(cs, "!") 198*2810ac1bSKiyoung Kim } 199*2810ac1bSKiyoung Kim if a { 200*2810ac1bSKiyoung Kim cs = append(cs, "^") 201*2810ac1bSKiyoung Kim } else if nb && i { 202*2810ac1bSKiyoung Kim cs = append(cs, "%") 203*2810ac1bSKiyoung Kim } 204*2810ac1bSKiyoung Kim if nb || a || i { 205*2810ac1bSKiyoung Kim vs = append(vs, strings.Join(cs, "")+c.String()) 206*2810ac1bSKiyoung Kim } 207*2810ac1bSKiyoung Kim } 208*2810ac1bSKiyoung Kim return strings.Join(vs, ",") 209*2810ac1bSKiyoung Kim} 210*2810ac1bSKiyoung Kim 211*2810ac1bSKiyoung Kim// iabSetProc uses a syscaller to apply an IAB tuple to the process. 212*2810ac1bSKiyoung Kim// The iab is known to be locked by the caller. 213*2810ac1bSKiyoung Kimfunc (sc *syscaller) iabSetProc(iab *IAB) (err error) { 214*2810ac1bSKiyoung Kim temp := GetProc() 215*2810ac1bSKiyoung Kim var raising uint32 216*2810ac1bSKiyoung Kim for i := 0; i < words; i++ { 217*2810ac1bSKiyoung Kim newI := iab.i[i] 218*2810ac1bSKiyoung Kim oldIP := temp.flat[i][Inheritable] | temp.flat[i][Permitted] 219*2810ac1bSKiyoung Kim raising |= (newI & ^oldIP) | iab.a[i] | iab.nb[i] 220*2810ac1bSKiyoung Kim temp.flat[i][Inheritable] = newI 221*2810ac1bSKiyoung Kim } 222*2810ac1bSKiyoung Kim working, err2 := temp.Dup() 223*2810ac1bSKiyoung Kim if err2 != nil { 224*2810ac1bSKiyoung Kim err = err2 225*2810ac1bSKiyoung Kim return 226*2810ac1bSKiyoung Kim } 227*2810ac1bSKiyoung Kim if raising != 0 { 228*2810ac1bSKiyoung Kim if err = working.SetFlag(Effective, true, SETPCAP); err != nil { 229*2810ac1bSKiyoung Kim return 230*2810ac1bSKiyoung Kim } 231*2810ac1bSKiyoung Kim if err = sc.setProc(working); err != nil { 232*2810ac1bSKiyoung Kim return 233*2810ac1bSKiyoung Kim } 234*2810ac1bSKiyoung Kim } 235*2810ac1bSKiyoung Kim defer func() { 236*2810ac1bSKiyoung Kim if err2 := sc.setProc(temp); err == nil { 237*2810ac1bSKiyoung Kim err = err2 238*2810ac1bSKiyoung Kim } 239*2810ac1bSKiyoung Kim }() 240*2810ac1bSKiyoung Kim if err = sc.resetAmbient(); err != nil { 241*2810ac1bSKiyoung Kim return 242*2810ac1bSKiyoung Kim } 243*2810ac1bSKiyoung Kim for c := Value(maxValues); c > 0; { 244*2810ac1bSKiyoung Kim c-- 245*2810ac1bSKiyoung Kim offset, mask := omask(c) 246*2810ac1bSKiyoung Kim if iab.a[offset]&mask != 0 { 247*2810ac1bSKiyoung Kim err = sc.setAmbient(true, c) 248*2810ac1bSKiyoung Kim } 249*2810ac1bSKiyoung Kim if err == nil && iab.nb[offset]&mask != 0 { 250*2810ac1bSKiyoung Kim err = sc.dropBound(c) 251*2810ac1bSKiyoung Kim } 252*2810ac1bSKiyoung Kim if err != nil { 253*2810ac1bSKiyoung Kim return 254*2810ac1bSKiyoung Kim } 255*2810ac1bSKiyoung Kim } 256*2810ac1bSKiyoung Kim return 257*2810ac1bSKiyoung Kim} 258*2810ac1bSKiyoung Kim 259*2810ac1bSKiyoung Kim// SetProc attempts to change the Inheritable, Ambient and Bounding 260*2810ac1bSKiyoung Kim// capability vectors of the current process using the content, 261*2810ac1bSKiyoung Kim// iab. The Bounding vector strongly affects the potential for setting 262*2810ac1bSKiyoung Kim// other bits, so this function carefully performs the combined 263*2810ac1bSKiyoung Kim// operation in the most flexible manner. 264*2810ac1bSKiyoung Kimfunc (iab *IAB) SetProc() error { 265*2810ac1bSKiyoung Kim if err := iab.good(); err != nil { 266*2810ac1bSKiyoung Kim return err 267*2810ac1bSKiyoung Kim } 268*2810ac1bSKiyoung Kim state, sc := scwStateSC() 269*2810ac1bSKiyoung Kim defer scwSetState(launchBlocked, state, -1) 270*2810ac1bSKiyoung Kim iab.mu.RLock() 271*2810ac1bSKiyoung Kim defer iab.mu.RUnlock() 272*2810ac1bSKiyoung Kim return sc.iabSetProc(iab) 273*2810ac1bSKiyoung Kim} 274*2810ac1bSKiyoung Kim 275*2810ac1bSKiyoung Kim// GetVector returns the raised state of the specific capability bit 276*2810ac1bSKiyoung Kim// of the indicated vector. 277*2810ac1bSKiyoung Kimfunc (iab *IAB) GetVector(vec Vector, val Value) (bool, error) { 278*2810ac1bSKiyoung Kim if err := iab.good(); err != nil { 279*2810ac1bSKiyoung Kim return false, err 280*2810ac1bSKiyoung Kim } 281*2810ac1bSKiyoung Kim if val >= MaxBits() { 282*2810ac1bSKiyoung Kim return false, ErrBadValue 283*2810ac1bSKiyoung Kim } 284*2810ac1bSKiyoung Kim iab.mu.RLock() 285*2810ac1bSKiyoung Kim defer iab.mu.RUnlock() 286*2810ac1bSKiyoung Kim offset, mask := omask(val) 287*2810ac1bSKiyoung Kim switch vec { 288*2810ac1bSKiyoung Kim case Inh: 289*2810ac1bSKiyoung Kim return (iab.i[offset] & mask) != 0, nil 290*2810ac1bSKiyoung Kim case Amb: 291*2810ac1bSKiyoung Kim return (iab.a[offset] & mask) != 0, nil 292*2810ac1bSKiyoung Kim case Bound: 293*2810ac1bSKiyoung Kim return (iab.nb[offset] & mask) != 0, nil 294*2810ac1bSKiyoung Kim default: 295*2810ac1bSKiyoung Kim return false, ErrBadValue 296*2810ac1bSKiyoung Kim } 297*2810ac1bSKiyoung Kim} 298*2810ac1bSKiyoung Kim 299*2810ac1bSKiyoung Kim// SetVector sets all of the vals in the specified vector to the 300*2810ac1bSKiyoung Kim// raised value. Note, the Ambient vector cannot contain values not raised 301*2810ac1bSKiyoung Kim// in the Inh vector, so setting values directly in one vector may have 302*2810ac1bSKiyoung Kim// the side effect of mirroring the value in the other vector to 303*2810ac1bSKiyoung Kim// maintain this constraint. Note, raising a Bound vector bit is 304*2810ac1bSKiyoung Kim// equivalent to lowering the Bounding vector of the process (when 305*2810ac1bSKiyoung Kim// successfully applied with (*IAB).SetProc()). 306*2810ac1bSKiyoung Kimfunc (iab *IAB) SetVector(vec Vector, raised bool, vals ...Value) error { 307*2810ac1bSKiyoung Kim if err := iab.good(); err != nil { 308*2810ac1bSKiyoung Kim return err 309*2810ac1bSKiyoung Kim } 310*2810ac1bSKiyoung Kim iab.mu.Lock() 311*2810ac1bSKiyoung Kim defer iab.mu.Unlock() 312*2810ac1bSKiyoung Kim for _, val := range vals { 313*2810ac1bSKiyoung Kim if val >= Value(maxValues) { 314*2810ac1bSKiyoung Kim return ErrBadValue 315*2810ac1bSKiyoung Kim } 316*2810ac1bSKiyoung Kim offset, mask := omask(val) 317*2810ac1bSKiyoung Kim switch vec { 318*2810ac1bSKiyoung Kim case Inh: 319*2810ac1bSKiyoung Kim if raised { 320*2810ac1bSKiyoung Kim iab.i[offset] |= mask 321*2810ac1bSKiyoung Kim } else { 322*2810ac1bSKiyoung Kim iab.i[offset] &= ^mask 323*2810ac1bSKiyoung Kim iab.a[offset] &= ^mask 324*2810ac1bSKiyoung Kim } 325*2810ac1bSKiyoung Kim case Amb: 326*2810ac1bSKiyoung Kim if raised { 327*2810ac1bSKiyoung Kim iab.a[offset] |= mask 328*2810ac1bSKiyoung Kim iab.i[offset] |= mask 329*2810ac1bSKiyoung Kim } else { 330*2810ac1bSKiyoung Kim iab.a[offset] &= ^mask 331*2810ac1bSKiyoung Kim } 332*2810ac1bSKiyoung Kim case Bound: 333*2810ac1bSKiyoung Kim if raised { 334*2810ac1bSKiyoung Kim iab.nb[offset] |= mask 335*2810ac1bSKiyoung Kim } else { 336*2810ac1bSKiyoung Kim iab.nb[offset] &= ^mask 337*2810ac1bSKiyoung Kim } 338*2810ac1bSKiyoung Kim default: 339*2810ac1bSKiyoung Kim return ErrBadValue 340*2810ac1bSKiyoung Kim } 341*2810ac1bSKiyoung Kim } 342*2810ac1bSKiyoung Kim return nil 343*2810ac1bSKiyoung Kim} 344*2810ac1bSKiyoung Kim 345*2810ac1bSKiyoung Kim// Fill fills one of the Inh, Amb and Bound capability vectors from 346*2810ac1bSKiyoung Kim// one of the flag vectors of a Set. Note, filling the Inh vector 347*2810ac1bSKiyoung Kim// will mask the Amb vector, and filling the Amb vector may raise 348*2810ac1bSKiyoung Kim// entries in the Inh vector. Further, when filling the Bound vector, 349*2810ac1bSKiyoung Kim// the bits are inverted from what you might expect - that is lowered 350*2810ac1bSKiyoung Kim// bits from the Set will be raised in the Bound vector. 351*2810ac1bSKiyoung Kimfunc (iab *IAB) Fill(vec Vector, c *Set, flag Flag) error { 352*2810ac1bSKiyoung Kim if err := iab.good(); err != nil { 353*2810ac1bSKiyoung Kim return err 354*2810ac1bSKiyoung Kim } 355*2810ac1bSKiyoung Kim // work with a copy to avoid potential deadlock. 356*2810ac1bSKiyoung Kim s, err := c.Dup() 357*2810ac1bSKiyoung Kim if err != nil { 358*2810ac1bSKiyoung Kim return err 359*2810ac1bSKiyoung Kim } 360*2810ac1bSKiyoung Kim iab.mu.Lock() 361*2810ac1bSKiyoung Kim defer iab.mu.Unlock() 362*2810ac1bSKiyoung Kim for i := 0; i < words; i++ { 363*2810ac1bSKiyoung Kim flat := s.flat[i][flag] 364*2810ac1bSKiyoung Kim switch vec { 365*2810ac1bSKiyoung Kim case Inh: 366*2810ac1bSKiyoung Kim iab.i[i] = flat 367*2810ac1bSKiyoung Kim iab.a[i] &= flat 368*2810ac1bSKiyoung Kim case Amb: 369*2810ac1bSKiyoung Kim iab.a[i] = flat 370*2810ac1bSKiyoung Kim iab.i[i] |= flat 371*2810ac1bSKiyoung Kim case Bound: 372*2810ac1bSKiyoung Kim iab.nb[i] = ^flat 373*2810ac1bSKiyoung Kim default: 374*2810ac1bSKiyoung Kim return ErrBadSet 375*2810ac1bSKiyoung Kim } 376*2810ac1bSKiyoung Kim } 377*2810ac1bSKiyoung Kim return nil 378*2810ac1bSKiyoung Kim} 379*2810ac1bSKiyoung Kim 380*2810ac1bSKiyoung Kim// Cf compares two IAB values. Its return value is 0 if the compared 381*2810ac1bSKiyoung Kim// tuples are considered identical. The macroscopic differences can be 382*2810ac1bSKiyoung Kim// investigated with (IABDiff).Has(). 383*2810ac1bSKiyoung Kimfunc (iab *IAB) Cf(alt *IAB) (IABDiff, error) { 384*2810ac1bSKiyoung Kim if err := iab.good(); err != nil { 385*2810ac1bSKiyoung Kim return 0, err 386*2810ac1bSKiyoung Kim } 387*2810ac1bSKiyoung Kim if iab == alt { 388*2810ac1bSKiyoung Kim return 0, nil 389*2810ac1bSKiyoung Kim } 390*2810ac1bSKiyoung Kim // Avoid holding two locks at once. 391*2810ac1bSKiyoung Kim ref, err := alt.Dup() 392*2810ac1bSKiyoung Kim if err != nil { 393*2810ac1bSKiyoung Kim return 0, err 394*2810ac1bSKiyoung Kim } 395*2810ac1bSKiyoung Kim iab.mu.RLock() 396*2810ac1bSKiyoung Kim defer iab.mu.RUnlock() 397*2810ac1bSKiyoung Kim 398*2810ac1bSKiyoung Kim var cf IABDiff 399*2810ac1bSKiyoung Kim for i := 0; i < words; i++ { 400*2810ac1bSKiyoung Kim if iab.i[i] != ref.i[i] { 401*2810ac1bSKiyoung Kim cf |= iBits 402*2810ac1bSKiyoung Kim } 403*2810ac1bSKiyoung Kim if iab.a[i] != ref.a[i] { 404*2810ac1bSKiyoung Kim cf |= aBits 405*2810ac1bSKiyoung Kim } 406*2810ac1bSKiyoung Kim if iab.nb[i] != ref.nb[i] { 407*2810ac1bSKiyoung Kim cf |= bBits 408*2810ac1bSKiyoung Kim } 409*2810ac1bSKiyoung Kim } 410*2810ac1bSKiyoung Kim return cf, nil 411*2810ac1bSKiyoung Kim} 412*2810ac1bSKiyoung Kim 413*2810ac1bSKiyoung Kim// parseHex converts the /proc/*/status string into an array of 414*2810ac1bSKiyoung Kim// uint32s suitable for storage in an IAB structure. 415*2810ac1bSKiyoung Kimfunc parseHex(hex string, invert bool) []uint32 { 416*2810ac1bSKiyoung Kim if len(hex) != 8*words { 417*2810ac1bSKiyoung Kim // Invalid string 418*2810ac1bSKiyoung Kim return nil 419*2810ac1bSKiyoung Kim } 420*2810ac1bSKiyoung Kim var result []uint32 421*2810ac1bSKiyoung Kim for i := 0; i < words; i++ { 422*2810ac1bSKiyoung Kim upper := 8 * (words - i) 423*2810ac1bSKiyoung Kim raw, err := strconv.ParseUint(hex[upper-8:upper], 16, 32) 424*2810ac1bSKiyoung Kim if err != nil { 425*2810ac1bSKiyoung Kim return nil 426*2810ac1bSKiyoung Kim } 427*2810ac1bSKiyoung Kim if invert { 428*2810ac1bSKiyoung Kim raw = ^raw 429*2810ac1bSKiyoung Kim } 430*2810ac1bSKiyoung Kim bits := allMask(uint(i)) & uint32(raw) 431*2810ac1bSKiyoung Kim result = append(result, bits) 432*2810ac1bSKiyoung Kim } 433*2810ac1bSKiyoung Kim return result 434*2810ac1bSKiyoung Kim} 435*2810ac1bSKiyoung Kim 436*2810ac1bSKiyoung Kimvar procRoot = "/proc" 437*2810ac1bSKiyoung Kim 438*2810ac1bSKiyoung Kim// ProcRoot sets the local mount point for the Linux /proc filesystem. 439*2810ac1bSKiyoung Kim// It defaults to "/proc", but might be mounted elsewhere on any given 440*2810ac1bSKiyoung Kim// system. The function returns the previous value of the local mount 441*2810ac1bSKiyoung Kim// point. If the user attempts to set it to "", the value is left 442*2810ac1bSKiyoung Kim// unchanged. 443*2810ac1bSKiyoung Kimfunc ProcRoot(path string) string { 444*2810ac1bSKiyoung Kim was := procRoot 445*2810ac1bSKiyoung Kim if path != "" { 446*2810ac1bSKiyoung Kim procRoot = path 447*2810ac1bSKiyoung Kim } 448*2810ac1bSKiyoung Kim return was 449*2810ac1bSKiyoung Kim} 450*2810ac1bSKiyoung Kim 451*2810ac1bSKiyoung Kim// IABGetPID returns the IAB tuple of a specified process. The kernel 452*2810ac1bSKiyoung Kim// ABI does not support this query via system calls, so the function 453*2810ac1bSKiyoung Kim// works by parsing the /proc/<pid>/status file content. 454*2810ac1bSKiyoung Kimfunc IABGetPID(pid int) (*IAB, error) { 455*2810ac1bSKiyoung Kim tf := fmt.Sprintf("%s/%d/status", procRoot, pid) 456*2810ac1bSKiyoung Kim d, err := ioutil.ReadFile(tf) 457*2810ac1bSKiyoung Kim if err != nil { 458*2810ac1bSKiyoung Kim return nil, err 459*2810ac1bSKiyoung Kim } 460*2810ac1bSKiyoung Kim iab := &IAB{} 461*2810ac1bSKiyoung Kim for _, line := range strings.Split(string(d), "\n") { 462*2810ac1bSKiyoung Kim if !strings.HasPrefix(line, "Cap") { 463*2810ac1bSKiyoung Kim continue 464*2810ac1bSKiyoung Kim } 465*2810ac1bSKiyoung Kim flavor := line[3:] 466*2810ac1bSKiyoung Kim if strings.HasPrefix(flavor, "Inh:\t") { 467*2810ac1bSKiyoung Kim iab.i = parseHex(line[8:], false) 468*2810ac1bSKiyoung Kim continue 469*2810ac1bSKiyoung Kim } 470*2810ac1bSKiyoung Kim if strings.HasPrefix(flavor, "Bnd:\t") { 471*2810ac1bSKiyoung Kim iab.nb = parseHex(line[8:], true) 472*2810ac1bSKiyoung Kim continue 473*2810ac1bSKiyoung Kim } 474*2810ac1bSKiyoung Kim if strings.HasPrefix(flavor, "Amb:\t") { 475*2810ac1bSKiyoung Kim iab.a = parseHex(line[8:], false) 476*2810ac1bSKiyoung Kim continue 477*2810ac1bSKiyoung Kim } 478*2810ac1bSKiyoung Kim } 479*2810ac1bSKiyoung Kim if len(iab.i) != words || len(iab.a) != words || len(iab.nb) != words { 480*2810ac1bSKiyoung Kim return nil, ErrBadValue 481*2810ac1bSKiyoung Kim } 482*2810ac1bSKiyoung Kim return iab, nil 483*2810ac1bSKiyoung Kim} 484