eval.bend
bend-osdev-apparmor@0.1.0.0 · 234 lines · 31 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import Base
20import bend-osdev-apparmor@0.1.0.0/perm.bend as P
21import bend-osdev-apparmor@0.1.0.0/options.bend as O
22import bend-osdev-apparmor@0.1.0.0/profile.bend as PR
23import bend-osdev-apparmor@0.1.0.0/rule_file.bend as F
24import bend-osdev-apparmor@0.1.0.0/rule_capability.bend as RC
25import bend-osdev-apparmor@0.1.0.0/rule_network.bend as RN
26import bend-osdev-apparmor@0.1.0.0/rule_signal.bend as RS
27import bend-osdev-apparmor@0.1.0.0/rule_ptrace.bend as RP
28import bend-osdev-apparmor@0.1.0.0/rule_mount.bend as RM
29import bend-osdev-apparmor@0.1.0.0/rule_dbus.bend as RD
30import bend-osdev-apparmor@0.1.0.0/rule_change_profile.bend as RX
31
32type AaDecision is Data:
33
34 AaAllow{}
35
36 AaAudit{}
37
38 AaComplain{}
39
40 AaDeny{logged: Bool}
41
42 AaKill{}
43
44def AaDecision.allowed(d: AaDecision) -> Bool:
45 match d:
46 case AaAllow{}:
47 True{}
48 case AaAudit{}:
49 True{}
50 case AaComplain{}:
51 True{}
52 case AaDeny{l}:
53 False{}
54 case AaKill{}:
55 False{}
56
57def AaDecision.show(d: AaDecision) -> String:
58 match d:
59 case AaAllow{}:
60 "allow"
61 case AaAudit{}:
62 "audit"
63 case AaComplain{}:
64 "complain"
65 case AaDeny{l}:
66 Bool.pick(String, l, "deny", "deny-quiet")
67 case AaKill{}:
68 "kill"
69
70
71
72type AaAcc is Data:
73 AaAcc{allow: P.AaPerms, deny: P.AaPerms, audit: P.AaPerms, quiet: P.AaPerms}
74
75def AaAcc.empty() -> AaAcc:
76 AaAcc{P.AaPerms.none(), P.AaPerms.none(), P.AaPerms.none(), P.AaPerms.none()}
77
78
79def AaAcc.join(a: AaAcc, b: AaAcc) -> AaAcc:
80 match a b:
81 case AaAcc{al, de, au, qu} AaAcc{al2, de2, au2, qu2}:
82 AaAcc{P.AaPerms.union(al, al2), P.AaPerms.union(de, de2), P.AaPerms.union(au, au2), P.AaPerms.union(qu, qu2)}
83
84
85
86def AaAcc.single.go(audit: Bool, deny: Bool, +p: P.AaPerms) -> AaAcc:
87 match audit:
88 case True{}:
89 match deny:
90 case True{}:
91 AaAcc{P.AaPerms.none(), p, p, P.AaPerms.none()}
92 case False{}:
93 AaAcc{p, P.AaPerms.none(), p, P.AaPerms.none()}
94 case False{}:
95 match deny:
96 case True{}:
97 AaAcc{P.AaPerms.none(), p, P.AaPerms.none(), p}
98 case False{}:
99 AaAcc{p, P.AaPerms.none(), P.AaPerms.none(), P.AaPerms.none()}
100
101def AaAcc.single(g: P.AaGrant) -> AaAcc:
102 match g:
103 case P.AaGrant{audit, deny, p}:
104 AaAcc.single.go(audit, deny, p)
105
106def AaAcc.add(a: AaAcc, g: P.AaGrant) -> AaAcc:
107 AaAcc.join(a, AaAcc.single(g))
108
109def AaAcc.from(gs: List<&2, P.AaGrant>, a: AaAcc) -> AaAcc:
110 match gs:
111 case Nil{}:
112 a
113 case Con{g, t}:
114 AaAcc.from(t, AaAcc.add(a, g))
115
116def AaAcc.of(gs: List<&2, P.AaGrant>) -> AaAcc:
117 AaAcc.from(gs, AaAcc.empty())
118
119def AaAcc.allow(a: AaAcc) -> P.AaPerms:
120 match a:
121 case AaAcc{al, de, au, qu}:
122 al
123
124def AaAcc.deny(a: AaAcc) -> P.AaPerms:
125 match a:
126 case AaAcc{al, de, au, qu}:
127 de
128
129def AaAcc.audit(a: AaAcc) -> P.AaPerms:
130 match a:
131 case AaAcc{al, de, au, qu}:
132 au
133
134def AaAcc.quiet(a: AaAcc) -> P.AaPerms:
135 match a:
136 case AaAcc{al, de, au, qu}:
137 qu
138
139
140def AaAcc.granted(a: AaAcc) -> P.AaPerms:
141 match a:
142 case AaAcc{al, de, au, qu}:
143 P.AaPerms.minus(al, de)
144
145def AaEval.granted(gs: List<&2, P.AaGrant>) -> P.AaPerms:
146 AaAcc.granted(AaAcc.of(gs))
147
148
149def AaEval.denied(gs: List<&2, P.AaGrant>) -> P.AaPerms:
150 AaAcc.deny(AaAcc.of(gs))
151
152
153
154def AaEval.choose(c: Bool, a: AaDecision, b: AaDecision) -> AaDecision:
155 match c:
156 case True{}:
157 a
158 case False{}:
159 b
160
161
162
163def AaEval.decide.mode(m: PR.AaMode, cov: Bool, hit: Bool, cd: Bool, ok: AaDecision, no: AaDecision) -> AaDecision:
164 match m:
165 case PR.AaModeEnforce{}:
166 AaEval.choose(cov, ok, no)
167 case PR.AaModePrompt{}:
168 AaEval.choose(cov, ok, no)
169 case PR.AaModeKill{}:
170 AaEval.choose(cov, ok, AaKill{})
171 case PR.AaModeComplain{}:
172 AaEval.choose(cov, ok, AaEval.choose(Bool.and(cd, hit), no, AaComplain{}))
173 case PR.AaModeDefaultAllow{}:
174 AaEval.choose(hit, no, ok)
175 case PR.AaModeUnconfined{}:
176 AaAllow{}
177
178def AaEval.decide.acc(opts: O.AaOptions, flags: PR.AaFlags, +req: P.AaPerms, a: AaAcc) -> AaDecision:
179 match flags:
180 case PR.AaFlags{m, +fa}:
181 match a:
182 case AaAcc{al, +de, +au, qu}:
183 +granted = P.AaPerms.minus(al, de)
184 AaEval.decide.mode(m, P.AaPerms.covers(granted, req), P.AaPerms.meets(req, de), O.AaOptions.complain_deny(opts), AaEval.choose(Bool.or(fa, P.AaPerms.meets(req, au)), AaAudit{}, AaAllow{}), AaDeny{Bool.or(fa, Bool.not(P.AaPerms.covers(P.AaPerms.minus(qu, au), P.AaPerms.minus(req, granted))))})
185
186
187
188def AaEval.decide(opts: O.AaOptions, flags: PR.AaFlags, +req: P.AaPerms, gs: List<&2, P.AaGrant>) -> AaDecision:
189 AaEval.decide.acc(opts, flags, req, AaAcc.of(gs))
190
191
192
193def AaEval.deny_applies(opts: O.AaOptions, m: PR.AaMode) -> Bool:
194 match m:
195 case PR.AaModeUnconfined{}:
196 False{}
197 case PR.AaModeComplain{}:
198 O.AaOptions.complain_deny(opts)
199 case PR.AaModeEnforce{}:
200 True{}
201 case PR.AaModeKill{}:
202 True{}
203 case PR.AaModePrompt{}:
204 True{}
205 case PR.AaModeDefaultAllow{}:
206 True{}
207
208
209
210def AaEval.file(opts: O.AaOptions, +p: PR.AaProfile, +q: F.AaFileQuery) -> AaDecision:
211 match q:
212 case F.AaFileQuery{path, owner, req}:
213 AaEval.decide(opts, PR.AaProfile.flags(p), req, F.AaFileRule.grants(PR.AaRules.files(PR.AaProfile.rules(p)), F.AaFileQuery{path, owner, req}))
214
215def AaEval.capability(opts: O.AaOptions, +p: PR.AaProfile, +q: RC.AaCapQuery) -> AaDecision:
216 AaEval.decide(opts, PR.AaProfile.flags(p), RC.AaCapQuery.req(), RC.AaCapRule.grants(PR.AaRules.caps(PR.AaProfile.rules(p)), q))
217
218def AaEval.network(opts: O.AaOptions, +p: PR.AaProfile, +q: RN.AaNetQuery) -> AaDecision:
219 AaEval.decide(opts, PR.AaProfile.flags(p), RN.AaNetQuery.req(), RN.AaNetRule.grants(PR.AaRules.nets(PR.AaProfile.rules(p)), q))
220
221def AaEval.signal(opts: O.AaOptions, +p: PR.AaProfile, +q: RS.AaSignalQuery) -> AaDecision:
222 AaEval.decide(opts, PR.AaProfile.flags(p), RS.AaSignalQuery.req(q), RS.AaSignalRule.grants(PR.AaRules.signals(PR.AaProfile.rules(p)), q))
223
224def AaEval.ptrace(opts: O.AaOptions, +p: PR.AaProfile, +q: RP.AaPtraceQuery) -> AaDecision:
225 AaEval.decide(opts, PR.AaProfile.flags(p), RP.AaPtraceQuery.req(q), RP.AaPtraceRule.grants(PR.AaRules.ptraces(PR.AaProfile.rules(p)), q))
226
227def AaEval.mount(opts: O.AaOptions, +p: PR.AaProfile, +q: RM.AaMountQuery) -> AaDecision:
228 AaEval.decide(opts, PR.AaProfile.flags(p), RM.AaMountQuery.req(), RM.AaMountRule.grants(PR.AaRules.mounts(PR.AaProfile.rules(p)), q))
229
230def AaEval.dbus(opts: O.AaOptions, +p: PR.AaProfile, +q: RD.AaDbusQuery) -> AaDecision:
231 AaEval.decide(opts, PR.AaProfile.flags(p), RD.AaDbusQuery.req(q), RD.AaDbusRule.grants(PR.AaRules.dbus(PR.AaProfile.rules(p)), q))
232
233def AaEval.change_profile(opts: O.AaOptions, +p: PR.AaProfile, +q: RX.AaChangeQuery) -> AaDecision:
234 AaEval.decide(opts, PR.AaProfile.flags(p), RX.AaChangeQuery.req(), RX.AaChangeRule.grants(PR.AaRules.changes(PR.AaProfile.rules(p)), q))