Replace checkPermBits error-return with hasPermBits bool
- hasPermBits uses a 4-entry mask array indexed by mode&3 to select the required permission bits: OREAD→4, OWRITE→2, ORDWR→6, OEXEC→1 - Zero branches, zero error paths — returns bits&mask == mask - open() uses OR semantics: checks owner, group, world independently; any tier granting access is sufficient - checkPerm removed entirely; permission logic is pure boolean math
This commit is contained in:
parent
325ad224be
commit
0b4daf016a
|
|
@ -144,35 +144,11 @@ func fileOwnerGroup(root *fs.Tree, path string) (uid, gid string) {
|
||||||
return "ollie", "agent"
|
return "ollie", "agent"
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPerm(uname string, mode uint8, uid string, perm uint32, inGroup bool) error {
|
var permMask = [4]uint32{4, 2, 6, 1} // OREAD, OWRITE, ORDWR, OEXEC
|
||||||
var bits uint32
|
|
||||||
if uname == uid {
|
func hasPermBits(mode uint8, bits uint32) bool {
|
||||||
bits = (perm >> 6) & 7
|
m := permMask[mode&3]
|
||||||
} else if inGroup {
|
return bits&m == m
|
||||||
bits = (perm >> 3) & 7
|
|
||||||
} else {
|
|
||||||
bits = perm & 7
|
|
||||||
}
|
|
||||||
omode := mode & 3
|
|
||||||
switch omode {
|
|
||||||
case plan9.OREAD:
|
|
||||||
if bits&4 == 0 {
|
|
||||||
return fmt.Errorf("permission denied")
|
|
||||||
}
|
|
||||||
case plan9.OWRITE:
|
|
||||||
if bits&2 == 0 {
|
|
||||||
return fmt.Errorf("permission denied")
|
|
||||||
}
|
|
||||||
case plan9.ORDWR:
|
|
||||||
if bits&6 != 6 {
|
|
||||||
return fmt.Errorf("permission denied")
|
|
||||||
}
|
|
||||||
case plan9.OEXEC:
|
|
||||||
if bits&1 == 0 {
|
|
||||||
return fmt.Errorf("permission denied")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const readTimeout = 10 * time.Second
|
const readTimeout = 10 * time.Second
|
||||||
|
|
@ -413,8 +389,20 @@ func (s *Server) open(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
|
||||||
return errFcall(fc, "bad fid")
|
return errFcall(fc, "bad fid")
|
||||||
}
|
}
|
||||||
uid, gid := fileOwnerGroup(s.rootTree, f.path)
|
uid, gid := fileOwnerGroup(s.rootTree, f.path)
|
||||||
if err := checkPerm(cs.uname, fc.Mode, uid, uint32(makeStat(s.rootTree, f.path).Mode)&0777, s.InGroup(gid, cs.uname)); err != nil {
|
perm := uint32(makeStat(s.rootTree, f.path).Mode) & 0777
|
||||||
return errFcall(fc, err.Error())
|
|
||||||
|
allowed := false
|
||||||
|
if cs.uname == uid {
|
||||||
|
allowed = hasPermBits(fc.Mode, perm>>6)
|
||||||
|
}
|
||||||
|
if !allowed && s.InGroup(gid, cs.uname) {
|
||||||
|
allowed = hasPermBits(fc.Mode, perm>>3)
|
||||||
|
}
|
||||||
|
if !allowed {
|
||||||
|
allowed = hasPermBits(fc.Mode, perm)
|
||||||
|
}
|
||||||
|
if !allowed {
|
||||||
|
return errFcall(fc, "permission denied")
|
||||||
}
|
}
|
||||||
f.mode = fc.Mode
|
f.mode = fc.Mode
|
||||||
return &plan9.Fcall{Type: plan9.Ropen, Tag: fc.Tag, Qid: f.qid}
|
return &plan9.Fcall{Type: plan9.Ropen, Tag: fc.Tag, Qid: f.qid}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue