返回 DeepSeek-Reasonix
acl.go
1 package packagegrant
2
3 import (
4 "encoding/binary"
5 "errors"
6 )
7
8 // Report is what one pass changed, what it found and could not change, and
9 // what it could not read. An unread object is not known to carry a grant.
10 type Report struct {
11 Stripped []string `json:"stripped"`
12 Refused []Failure `json:"refused"`
13 Unread []Failure `json:"unread"`
14 }
15
16 // Failure is one object the pass could not finish, and why.
17 type Failure struct {
18 Path string `json:"path"`
19 Err error `json:"-"`
20 }
21
22 // ErrMalformed marks an ACL whose sizes do not account for its bytes. Nothing is
23 // written back from one.
24 var ErrMalformed = errors.New("packagegrant: malformed ACL")
25
26 const (
27 aclHeaderSize = 8
28 aceHeaderSize = 4
29 aceMaskSize = 4
30
31 aceTypeAccessAllowed = 0x0
32 aceTypeAccessAllowedCallback = 0x9
33 aceFlagInherited = 0x10
34
35 sidMinSize = 8
36 appPackageAuthority = 15
37 appPackageBaseRID = 2
38 // SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT: the groups every package belongs to.
39 builtinPackageRIDCount = 2
40 )
41
42 // rewrite returns acl without the allow entries that name a specific package.
43 // changed is false when there were none. protect says the result must be
44 // written as a protected DACL: a removed entry was inherited, so the object
45 // stops inheriting and keeps the rest of what it had, now as its own entries.
46 func rewrite(acl []byte, wasProtected bool) (out []byte, protect, changed bool, err error) {
47 if len(acl) < aclHeaderSize {
48 return nil, false, false, ErrMalformed
49 }
50 size := int(binary.LittleEndian.Uint16(acl[2:4]))
51 count := int(binary.LittleEndian.Uint16(acl[4:6]))
52 if size < aclHeaderSize || size > len(acl) {
53 return nil, false, false, ErrMalformed
54 }
55 var kept [][]byte
56 inheritedRemoved := false
57 offset := aclHeaderSize
58 for range count {
59 if offset+aceHeaderSize > size {
60 return nil, false, false, ErrMalformed
61 }
62 aceSize := int(binary.LittleEndian.Uint16(acl[offset+2 : offset+4]))
63 if aceSize < aceHeaderSize || offset+aceSize > size {
64 return nil, false, false, ErrMalformed
65 }
66 ace := acl[offset : offset+aceSize]
67 offset += aceSize
68 if grantsSpecificPackage(ace) {
69 changed = true
70 inheritedRemoved = inheritedRemoved || ace[1]&aceFlagInherited != 0
71 continue
72 }
73 kept = append(kept, ace)
74 }
75 if !changed {
76 return nil, false, false, nil
77 }
78 total := aclHeaderSize
79 for _, ace := range kept {
80 total += len(ace)
81 }
82 out = make([]byte, aclHeaderSize, total)
83 out[0] = acl[0]
84 binary.LittleEndian.PutUint16(out[2:4], uint16(total))
85 binary.LittleEndian.PutUint16(out[4:6], uint16(len(kept)))
86 for _, ace := range kept {
87 start := len(out)
88 out = append(out, ace...)
89 if inheritedRemoved {
90 out[start+1] &^= aceFlagInherited
91 }
92 }
93 return out, wasProtected || inheritedRemoved, true, nil
94 }
95
96 // grantsSpecificPackage reports whether ace allows access to one app package
97 // rather than to a built-in package group. Entry types whose SID does not sit
98 // right after the mask are never matched, so they are always kept.
99 func grantsSpecificPackage(ace []byte) bool {
100 if ace[0] != aceTypeAccessAllowed && ace[0] != aceTypeAccessAllowedCallback {
101 return false
102 }
103 sid := ace[aceHeaderSize+aceMaskSize:]
104 if len(sid) < sidMinSize {
105 return false
106 }
107 subCount := int(sid[1])
108 if len(sid) < sidMinSize+4*subCount || subCount <= builtinPackageRIDCount {
109 return false
110 }
111 authority := sid[2:8]
112 for _, b := range authority[:5] {
113 if b != 0 {
114 return false
115 }
116 }
117 return authority[5] == appPackageAuthority && binary.LittleEndian.Uint32(sid[8:12]) == appPackageBaseRID
118 }
119
119 lines GO