exec.bend
bend-osdev-caps@0.1.0.0 · 179 lines · 20 definitions
1
2
3
4
5
6import Base
7import bend-osdev-caps@0.1.0.0/caps.bend as C
8
9
10
11
12
13type CapExecFlags is Data:
14 CapExecFlags{privileged: Bool, effective: Bool, permitted: C.CapSet(), inheritable: C.CapSet()}
15
16def CapExec.ambient(privileged: Bool, a: C.CapSet()) -> C.CapSet():
17 match privileged:
18 case True{}:
19 C.CapSet.empty()
20 case False{}:
21 a
22
23def CapExec.effective(effective: Bool, p: C.CapSet(), a: C.CapSet()) -> C.CapSet():
24 match effective:
25 case True{}:
26 p
27 case False{}:
28 a
29
30
31
32
33
34
35
36
37def CapExec.sets(fl: CapExecFlags, s: C.CapState) -> C.CapState:
38 match fl s:
39 case CapExecFlags{priv, feff, fp, fi} C.CapState{p, +i, e, +b, a}:
40 +a2 = CapExec.ambient(priv, a)
41 +p2 = C.CapSet.union(C.CapSet.union(C.CapSet.inter(i, fi), C.CapSet.inter(fp, b)), a2)
42 C.CapState{p2, i, CapExec.effective(feff, p2, a2), b, a2}
43
44
45
46def CapExec.euid(ign: Bool, setuid: Bool, owner: U32, euid: U32) -> U32:
47 match ign:
48 case True{}:
49 euid
50 case False{}:
51 match setuid:
52 case True{}:
53 owner
54 case False{}:
55 euid
56
57
58def CapExec.fcaps(ign: Bool, fc: Maybe<&2, C.CapFileSets>) -> Maybe<&2, C.CapFileSets>:
59 match ign:
60 case True{}:
61 None{}
62 case False{}:
63 fc
64
65def CapExec.has_caps(fc: Maybe<&2, C.CapFileSets>) -> Bool:
66 match fc:
67 case None{}:
68 False{}
69 case Some{x}:
70 True{}
71
72
73def CapExec.privileged(ign: Bool, setuid: Bool, setgid: Bool, fc: Maybe<&2, C.CapFileSets>) -> Bool:
74 match ign:
75 case True{}:
76 CapExec.has_caps(fc)
77 case False{}:
78 Bool.or(setuid, Bool.or(setgid, CapExec.has_caps(fc)))
79
80
81
82def CapExec.flags.file(priv: Bool, effective: Bool, fc: Maybe<&2, C.CapFileSets>) -> CapExecFlags:
83 match fc:
84 case None{}:
85 CapExecFlags{priv, effective, C.CapSet.empty(), C.CapSet.empty()}
86 case Some{C.CapFileSets{fp, fi, fe}}:
87 CapExecFlags{priv, Bool.or(effective, fe), fp, fi}
88
89
90
91def CapExec.flags.suid_root(priv: Bool, fc: Maybe<&2, C.CapFileSets>) -> CapExecFlags:
92 match fc:
93 case None{}:
94 CapExecFlags{priv, True{}, C.CapSet.full(), C.CapSet.full()}
95 case Some{C.CapFileSets{fp, fi, fe}}:
96 CapExecFlags{priv, True{}, fp, fi}
97
98def CapExec.fc_effective(fc: Maybe<&2, C.CapFileSets>) -> Bool:
99 match fc:
100 case None{}:
101 False{}
102 case Some{C.CapFileSets{fp, fi, fe}}:
103 fe
104
105
106
107
108
109
110
111def CapExec.flags.go(noroot: Bool, r0: Bool, e0: Bool, priv: Bool, fc: Maybe<&2, C.CapFileSets>) -> CapExecFlags:
112 match noroot:
113 case True{}:
114 CapExec.flags.file(priv, False{}, fc)
115 case False{}:
116 match r0:
117 case True{}:
118 CapExecFlags{priv, Bool.or(e0, CapExec.fc_effective(fc)), C.CapSet.full(), C.CapSet.full()}
119 case False{}:
120 match e0:
121 case True{}:
122 CapExec.flags.suid_root(priv, fc)
123 case False{}:
124 CapExec.flags.file(priv, False{}, fc)
125
126
127
128def CapExec.file_caps(k: C.CapsKernel, f: C.CapFile, ign: Bool) -> Maybe<&2, C.CapFileSets>:
129 match f:
130 case C.CapFile{u, su, sg, fc}:
131 CapExec.fcaps(Bool.or(ign, Bool.not(C.CapsKernel.file_caps(k))), fc)
132
133def CapExec.flags.mk(+fc2: Maybe<&2, C.CapFileSets>, c: C.CapCred, f: C.CapFile, +ign: Bool) -> CapExecFlags:
134 match c f:
135 case C.CapCred{r, e, s, nr, na, st} C.CapFile{u, +su, sg, fc}:
136 CapExec.flags.go(nr, U32.is_eq(r, 0), U32.is_eq(CapExec.euid(ign, su, u, e), 0), CapExec.privileged(ign, su, sg, fc2), fc2)
137
138def CapExec.flags(k: C.CapsKernel, c: C.CapCred, +f: C.CapFile, +ign: Bool) -> CapExecFlags:
139 CapExec.flags.mk(CapExec.file_caps(k, f, ign), c, f, ign)
140
141
142
143
144def Caps.execve.sets(k: C.CapsKernel, +c: C.CapCred, f: C.CapFile, ign: Bool) -> C.CapState:
145 CapExec.sets(CapExec.flags(k, c, f, ign), C.CapCred.sets(c))
146
147
148
149def CapExec.dumb_ok(fc: Maybe<&2, C.CapFileSets>, p: C.CapSet()) -> Bool:
150 match fc:
151 case None{}:
152 True{}
153 case Some{C.CapFileSets{fp, fi, fe}}:
154 match fe:
155 case False{}:
156 True{}
157 case True{}:
158 C.CapSet.subset(fp, p)
159
160def CapExec.fin(ok: Bool, c: C.CapCred, +euid: U32, s: C.CapState) -> Result<&2, &2, C.CapsError, C.CapCred>:
161 match ok:
162 case False{}:
163 Fail{C.CapsCapabilityDumb{}}
164 case True{}:
165 match c:
166 case C.CapCred{r, e, sv, nr, na, st}:
167 Done{C.CapCred{r, euid, euid, nr, na, s}}
168
169def CapExec.new_euid(c: C.CapCred, f: C.CapFile, ign: Bool) -> U32:
170 match c f:
171 case C.CapCred{r, e, s, nr, na, st} C.CapFile{u, su, sg, fc}:
172 CapExec.euid(ign, su, u, e)
173
174
175
176
177def Caps.execve(+k: C.CapsKernel, +c: C.CapCred, +f: C.CapFile, +ign: Bool) -> Result<&2, &2, C.CapsError, C.CapCred>:
178 +s = Caps.execve.sets(k, c, f, ign)
179 CapExec.fin(CapExec.dumb_ok(CapExec.file_caps(k, f, ign), C.CapState.permitted(s)), c, CapExec.new_euid(c, f, ign), s)