insn.bend
bend-osdev-bpf@0.1.0.0 · 482 lines · 44 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import Base
20import bend-osdev-bytes@0.1.0.0/bytes.bend as B
21
22
23
24type BpfSize is Data:
25 BpfW{}
26 BpfH{}
27 BpfB{}
28
29type BpfAluOp is Data:
30 BpfAdd{}
31 BpfSub{}
32 BpfMul{}
33 BpfDiv{}
34 BpfOr{}
35 BpfAnd{}
36 BpfLsh{}
37 BpfRsh{}
38 BpfMod{}
39 BpfXor{}
40
41type BpfCond is Data:
42 BpfJeq{}
43 BpfJgt{}
44 BpfJge{}
45 BpfJset{}
46
47
48type BpfSrc is Data:
49 BpfK{k: U32}
50 BpfX{}
51
52
53type BpfRval is Data:
54 BpfRetK{k: U32}
55 BpfRetA{}
56
57
58
59type BpfOp is Data:
60 BpfLdAbs{size: BpfSize, k: U32}
61 BpfLdInd{size: BpfSize, k: U32}
62 BpfLdImm{k: U32}
63 BpfLdLen{}
64 BpfLdMem{k: U32}
65 BpfLdxImm{k: U32}
66 BpfLdxMem{k: U32}
67 BpfLdxLen{}
68 BpfLdxMsh{k: U32}
69 BpfSt{k: U32}
70 BpfStx{k: U32}
71 BpfAlu{op: BpfAluOp, src: BpfSrc}
72 BpfNeg{}
73 BpfJa{k: U32}
74 BpfJmp{cond: BpfCond, src: BpfSrc, jt: U32, jf: U32}
75 BpfRet{rval: BpfRval}
76 BpfTax{}
77 BpfTxa{}
78
79
80type BpfRaw is Data:
81 BpfRaw{code: U32, jt: U32, jf: U32, k: U32}
82
83
84type BpfOrder is Data:
85 BpfBig{}
86 BpfLittle{}
87
88
89
90
91type BpfError is Data:
92 BpfErrBadCode{pc: Nat, code: U32}
93 BpfErrTruncated{len: Nat}
94 BpfErrStoredTooLong{max: Nat}
95 BpfErrEmpty{}
96 BpfErrTooLong{len: Nat}
97 BpfErrJump{pc: Nat}
98 BpfErrJumpField{pc: Nat}
99 BpfErrNoReturn{pc: Nat}
100 BpfErrScratch{pc: Nat}
101 BpfErrDivZero{pc: Nat}
102 BpfErrMemInit{pc: Nat}
103 BpfErrSeccompLoad{pc: Nat}
104 BpfErrSeccompInsn{pc: Nat}
105 BpfErrPathTooLong{total: Nat}
106 BpfErrFellOff{}
107 BpfErrBadScratch{k: U32}
108
109
110def bpf_memwords() -> U32:
111 16
112
113
114
115def bpf_stmt(code: U32, k: U32) -> BpfRaw:
116 BpfRaw{code, 0, 0, k}
117
118def bpf_jump(code: U32, k: U32, jt: U32, jf: U32) -> BpfRaw:
119 BpfRaw{code, jt, jf, k}
120
121def BpfRaw.code(r: BpfRaw) -> U32:
122 match r:
123 case BpfRaw{code, jt, jf, k}:
124 code
125
126
127
128def BpfSize.bits(s: BpfSize) -> U32:
129 match s:
130 case BpfW{}:
131 0
132 case BpfH{}:
133 8
134 case BpfB{}:
135 16
136
137def BpfAluOp.bits(o: BpfAluOp) -> U32:
138 match o:
139 case BpfAdd{}:
140 0
141 case BpfSub{}:
142 16
143 case BpfMul{}:
144 32
145 case BpfDiv{}:
146 48
147 case BpfOr{}:
148 64
149 case BpfAnd{}:
150 80
151 case BpfLsh{}:
152 96
153 case BpfRsh{}:
154 112
155 case BpfMod{}:
156 144
157 case BpfXor{}:
158 160
159
160def BpfCond.bits(c: BpfCond) -> U32:
161 match c:
162 case BpfJeq{}:
163 16
164 case BpfJgt{}:
165 32
166 case BpfJge{}:
167 48
168 case BpfJset{}:
169 64
170
171def BpfSrc.bits(s: BpfSrc) -> U32:
172 match s:
173 case BpfK{k}:
174 0
175 case BpfX{}:
176 8
177
178def BpfSrc.k(s: BpfSrc) -> U32:
179 match s:
180 case BpfK{k}:
181 k
182 case BpfX{}:
183 0
184
185def BpfRval.encode(r: BpfRval) -> BpfRaw:
186 match r:
187 case BpfRetK{k}:
188 BpfRaw{6, 0, 0, k}
189 case BpfRetA{}:
190 BpfRaw{22, 0, 0, 0}
191
192
193def BpfOp.encode(op: BpfOp) -> BpfRaw:
194 match op:
195 case BpfLdAbs{size, k}:
196 BpfRaw{U32.or(32, BpfSize.bits(size)), 0, 0, k}
197 case BpfLdInd{size, k}:
198 BpfRaw{U32.or(64, BpfSize.bits(size)), 0, 0, k}
199 case BpfLdImm{k}:
200 BpfRaw{0, 0, 0, k}
201 case BpfLdLen{}:
202 BpfRaw{128, 0, 0, 0}
203 case BpfLdMem{k}:
204 BpfRaw{96, 0, 0, k}
205 case BpfLdxImm{k}:
206 BpfRaw{1, 0, 0, k}
207 case BpfLdxMem{k}:
208 BpfRaw{97, 0, 0, k}
209 case BpfLdxLen{}:
210 BpfRaw{129, 0, 0, 0}
211 case BpfLdxMsh{k}:
212 BpfRaw{177, 0, 0, k}
213 case BpfSt{k}:
214 BpfRaw{2, 0, 0, k}
215 case BpfStx{k}:
216 BpfRaw{3, 0, 0, k}
217 case BpfAlu{o, +src}:
218 BpfRaw{U32.or(4, U32.or(BpfAluOp.bits(o), BpfSrc.bits(src))), 0, 0, BpfSrc.k(src)}
219 case BpfNeg{}:
220 BpfRaw{132, 0, 0, 0}
221 case BpfJa{k}:
222 BpfRaw{5, 0, 0, k}
223 case BpfJmp{c, +src, jt, jf}:
224 BpfRaw{U32.or(5, U32.or(BpfCond.bits(c), BpfSrc.bits(src))), jt, jf, BpfSrc.k(src)}
225 case BpfRet{r}:
226 BpfRval.encode(r)
227 case BpfTax{}:
228 BpfRaw{7, 0, 0, 0}
229 case BpfTxa{}:
230 BpfRaw{135, 0, 0, 0}
231
232
233
234def BpfRaw.decode.pick(hit: Bool, op: BpfOp, rest: Maybe<&2, BpfOp>) -> Maybe<&2, BpfOp>:
235 match hit:
236 case True{}:
237 Some{op}
238 case False{}:
239 rest
240
241
242
243def BpfRaw.decode(r: BpfRaw) -> Maybe<&2, BpfOp>:
244 match r:
245 case BpfRaw{+code, +jt, +jf, +k}:
246 BpfRaw.decode.pick(U32.is_eq(code, 32), BpfLdAbs{BpfW{}, k},
247 BpfRaw.decode.pick(U32.is_eq(code, 40), BpfLdAbs{BpfH{}, k},
248 BpfRaw.decode.pick(U32.is_eq(code, 48), BpfLdAbs{BpfB{}, k},
249 BpfRaw.decode.pick(U32.is_eq(code, 64), BpfLdInd{BpfW{}, k},
250 BpfRaw.decode.pick(U32.is_eq(code, 72), BpfLdInd{BpfH{}, k},
251 BpfRaw.decode.pick(U32.is_eq(code, 80), BpfLdInd{BpfB{}, k},
252 BpfRaw.decode.pick(U32.is_eq(code, 0), BpfLdImm{k},
253 BpfRaw.decode.pick(U32.is_eq(code, 128), BpfLdLen{},
254 BpfRaw.decode.pick(U32.is_eq(code, 96), BpfLdMem{k},
255 BpfRaw.decode.pick(U32.is_eq(code, 1), BpfLdxImm{k},
256 BpfRaw.decode.pick(U32.is_eq(code, 97), BpfLdxMem{k},
257 BpfRaw.decode.pick(U32.is_eq(code, 129), BpfLdxLen{},
258 BpfRaw.decode.pick(U32.is_eq(code, 177), BpfLdxMsh{k},
259 BpfRaw.decode.pick(U32.is_eq(code, 2), BpfSt{k},
260 BpfRaw.decode.pick(U32.is_eq(code, 3), BpfStx{k},
261 BpfRaw.decode.pick(U32.is_eq(code, 4), BpfAlu{BpfAdd{}, BpfK{k}},
262 BpfRaw.decode.pick(U32.is_eq(code, 12), BpfAlu{BpfAdd{}, BpfX{}},
263 BpfRaw.decode.pick(U32.is_eq(code, 20), BpfAlu{BpfSub{}, BpfK{k}},
264 BpfRaw.decode.pick(U32.is_eq(code, 28), BpfAlu{BpfSub{}, BpfX{}},
265 BpfRaw.decode.pick(U32.is_eq(code, 36), BpfAlu{BpfMul{}, BpfK{k}},
266 BpfRaw.decode.pick(U32.is_eq(code, 44), BpfAlu{BpfMul{}, BpfX{}},
267 BpfRaw.decode.pick(U32.is_eq(code, 52), BpfAlu{BpfDiv{}, BpfK{k}},
268 BpfRaw.decode.pick(U32.is_eq(code, 60), BpfAlu{BpfDiv{}, BpfX{}},
269 BpfRaw.decode.pick(U32.is_eq(code, 68), BpfAlu{BpfOr{}, BpfK{k}},
270 BpfRaw.decode.pick(U32.is_eq(code, 76), BpfAlu{BpfOr{}, BpfX{}},
271 BpfRaw.decode.pick(U32.is_eq(code, 84), BpfAlu{BpfAnd{}, BpfK{k}},
272 BpfRaw.decode.pick(U32.is_eq(code, 92), BpfAlu{BpfAnd{}, BpfX{}},
273 BpfRaw.decode.pick(U32.is_eq(code, 100), BpfAlu{BpfLsh{}, BpfK{k}},
274 BpfRaw.decode.pick(U32.is_eq(code, 108), BpfAlu{BpfLsh{}, BpfX{}},
275 BpfRaw.decode.pick(U32.is_eq(code, 116), BpfAlu{BpfRsh{}, BpfK{k}},
276 BpfRaw.decode.pick(U32.is_eq(code, 124), BpfAlu{BpfRsh{}, BpfX{}},
277 BpfRaw.decode.pick(U32.is_eq(code, 148), BpfAlu{BpfMod{}, BpfK{k}},
278 BpfRaw.decode.pick(U32.is_eq(code, 156), BpfAlu{BpfMod{}, BpfX{}},
279 BpfRaw.decode.pick(U32.is_eq(code, 164), BpfAlu{BpfXor{}, BpfK{k}},
280 BpfRaw.decode.pick(U32.is_eq(code, 172), BpfAlu{BpfXor{}, BpfX{}},
281 BpfRaw.decode.pick(U32.is_eq(code, 132), BpfNeg{},
282 BpfRaw.decode.pick(U32.is_eq(code, 5), BpfJa{k},
283 BpfRaw.decode.pick(U32.is_eq(code, 21), BpfJmp{BpfJeq{}, BpfK{k}, jt, jf},
284 BpfRaw.decode.pick(U32.is_eq(code, 29), BpfJmp{BpfJeq{}, BpfX{}, jt, jf},
285 BpfRaw.decode.pick(U32.is_eq(code, 37), BpfJmp{BpfJgt{}, BpfK{k}, jt, jf},
286 BpfRaw.decode.pick(U32.is_eq(code, 45), BpfJmp{BpfJgt{}, BpfX{}, jt, jf},
287 BpfRaw.decode.pick(U32.is_eq(code, 53), BpfJmp{BpfJge{}, BpfK{k}, jt, jf},
288 BpfRaw.decode.pick(U32.is_eq(code, 61), BpfJmp{BpfJge{}, BpfX{}, jt, jf},
289 BpfRaw.decode.pick(U32.is_eq(code, 69), BpfJmp{BpfJset{}, BpfK{k}, jt, jf},
290 BpfRaw.decode.pick(U32.is_eq(code, 77), BpfJmp{BpfJset{}, BpfX{}, jt, jf},
291 BpfRaw.decode.pick(U32.is_eq(code, 6), BpfRet{BpfRetK{k}},
292 BpfRaw.decode.pick(U32.is_eq(code, 22), BpfRet{BpfRetA{}},
293 BpfRaw.decode.pick(U32.is_eq(code, 7), BpfTax{},
294 BpfRaw.decode.pick(U32.is_eq(code, 135), BpfTxa{},
295 None{})))))))))))))))))))))))))))))))))))))))))))))))))
296
297
298
299
300
301
302def bpf_encode.ref(ops: List<&2, BpfOp>) -> List<&2, BpfRaw>:
303 match ops:
304 case Nil{}:
305 Nil{}
306 case Con{op, t}:
307 Con{BpfOp.encode(op), bpf_encode.ref(t)}
308
309
310def bpf_encode.go(ops: List<&2, BpfOp>, acc: List<&2, BpfRaw>) -> List<&2, BpfRaw>:
311 match ops:
312 case Nil{}:
313 acc
314 case Con{op, t}:
315 bpf_encode.go(t, Con{BpfOp.encode(op), acc})
316
317def bpf_encode(ops: List<&2, BpfOp>) -> List<&2, BpfRaw>:
318 List.reverse(&2, BpfRaw, bpf_encode.go(ops, Nil{}))
319
320def bpf_decode.cons(m: Maybe<&2, BpfOp>, e: BpfError, rest: Result<&2, &2, BpfError, List<&2, BpfOp>>) -> Result<&2, &2, BpfError, List<&2, BpfOp>>:
321 match m:
322 case None{}:
323 Fail{e}
324 case Some{op}:
325 match rest:
326 case Fail{f}:
327 Fail{f}
328 case Done{ops}:
329 Done{Con{op, ops}}
330
331def bpf_decode.ref.go(rs: List<&2, BpfRaw>, +pc: Nat) -> Result<&2, &2, BpfError, List<&2, BpfOp>>:
332 match rs:
333 case Nil{}:
334 Done{Nil{}}
335 case Con{+r, t}:
336 bpf_decode.cons(BpfRaw.decode(r), BpfErrBadCode{pc, BpfRaw.code(r)}, bpf_decode.ref.go(t, 1n+pc))
337
338def bpf_decode.ref(rs: List<&2, BpfRaw>) -> Result<&2, &2, BpfError, List<&2, BpfOp>>:
339 bpf_decode.ref.go(rs, 0n)
340
341
342def bpf_decode.push(m: Maybe<&2, BpfOp>, e: BpfError, acc: List<&2, BpfOp>) -> Result<&2, &2, BpfError, List<&2, BpfOp>>:
343 match m:
344 case None{}:
345 Fail{e}
346 case Some{op}:
347 Done{Con{op, acc}}
348
349
350
351def bpf_decode.go(rs: List<&2, BpfRaw>, +pc: Nat, a: Result<&2, &2, BpfError, List<&2, BpfOp>>) -> Result<&2, &2, BpfError, List<&2, BpfOp>>:
352 match rs:
353 case Nil{}:
354 match a:
355 case Fail{e}:
356 Fail{e}
357 case Done{acc}:
358 Done{List.reverse(&2, BpfOp, acc)}
359 case Con{+r, t}:
360 match a:
361 case Fail{e}:
362 Fail{e}
363 case Done{acc}:
364 bpf_decode.go(t, 1n+pc, bpf_decode.push(BpfRaw.decode(r), BpfErrBadCode{pc, BpfRaw.code(r)}, acc))
365
366
367def bpf_decode(rs: List<&2, BpfRaw>) -> Result<&2, &2, BpfError, List<&2, BpfOp>>:
368 bpf_decode.go(rs, 0n, Done{Nil{}})
369
370
371
372def BpfRaw.to_octets(order: BpfOrder, r: BpfRaw) -> B.Octets:
373 match order:
374 case BpfLittle{}:
375 match r:
376 case BpfRaw{code, jt, jf, k}:
377 B.Octets.concat([B.Octets.le16(code), B.Octets.of_list([jt, jf]), B.Octets.le32(k)])
378 case BpfBig{}:
379 match r:
380 case BpfRaw{code, jt, jf, k}:
381 B.Octets.concat([B.Octets.be16(code), B.Octets.of_list([jt, jf]), B.Octets.be32(k)])
382
383
384def bpf_to_octets.go(rs: List<&2, BpfRaw>, +order: BpfOrder, acc: List<&2, B.Octets>) -> List<&2, B.Octets>:
385 match rs:
386 case Nil{}:
387 acc
388 case Con{r, t}:
389 bpf_to_octets.go(t, order, Con{BpfRaw.to_octets(order, r), acc})
390
391def bpf_to_octets(+order: BpfOrder, rs: List<&2, BpfRaw>) -> B.Octets:
392 B.Octets.concat(List.reverse(&2, B.Octets, bpf_to_octets.go(rs, order, Nil{})))
393
394def bpf_field(m: Maybe<&2, U32>) -> U32:
395 Maybe.default(&2, U32, m, 0)
396
397def BpfRaw.of_octets(order: BpfOrder, +o: B.Octets) -> BpfRaw:
398 match order:
399 case BpfLittle{}:
400 BpfRaw{bpf_field(B.Octets.le16_at(o, 0n)), bpf_field(B.Octets.at(o, 2n)), bpf_field(B.Octets.at(o, 3n)), bpf_field(B.Octets.le32_at(o, 4n))}
401 case BpfBig{}:
402 BpfRaw{bpf_field(B.Octets.be16_at(o, 0n)), bpf_field(B.Octets.at(o, 2n)), bpf_field(B.Octets.at(o, 3n)), bpf_field(B.Octets.be32_at(o, 4n))}
403
404
405def bpf_of_octets.go(n: Nat, +order: BpfOrder, +o: B.Octets, acc: List<&2, BpfRaw>) -> List<&2, BpfRaw>:
406 match n:
407 case 0n:
408 List.reverse(&2, BpfRaw, acc)
409 case 1n+p:
410 bpf_of_octets.go(p, order, B.Octets.drop(8n, o), Con{BpfRaw.of_octets(order, B.Octets.take(8n, o)), acc})
411
412def bpf_of_octets.rem(r: Nat, q: Nat, +order: BpfOrder, +o: B.Octets, +len: Nat) -> Result<&2, &2, BpfError, List<&2, BpfRaw>>:
413 match r:
414 case 0n:
415 Done{bpf_of_octets.go(q, order, o, Nil{})}
416 case 1n+p:
417 Fail{BpfErrTruncated{len}}
418
419def bpf_of_octets.fin(+order: BpfOrder, +o: B.Octets, +len: Nat, qr: Nat & Nat) -> Result<&2, &2, BpfError, List<&2, BpfRaw>>:
420 (q, r) = qr
421 bpf_of_octets.rem(r, q, order, o, len)
422
423
424def bpf_of_octets.fits(over: Maybe<&2, U32>, max: Nat, +order: BpfOrder, +o: B.Octets) -> Result<&2, &2, BpfError, List<&2, BpfRaw>>:
425 match over:
426 case Some{b}:
427 Fail{BpfErrStoredTooLong{max}}
428 case None{}:
429 +len = B.Octets.len(o)
430 bpf_of_octets.fin(order, o, len, Nat.divmod(len, 8n))
431
432
433
434def bpf_octets_max() -> Nat:
435 32768n
436
437
438
439
440def bpf_of_octets_with(+max: Nat, +order: BpfOrder, +o: B.Octets) -> Result<&2, &2, BpfError, List<&2, BpfRaw>>:
441 bpf_of_octets.fits(B.Octets.at(o, max), max, order, o)
442
443
444def bpf_of_octets(+order: BpfOrder, o: B.Octets) -> Result<&2, &2, BpfError, List<&2, BpfRaw>>:
445 bpf_of_octets_with(bpf_octets_max(), order, o)
446
447
448
449def BpfError.show(e: BpfError) -> String:
450 match e:
451 case BpfErrBadCode{pc, code}:
452 "bad opcode " ++ U32.show(code) ++ " at " ++ Nat.show(pc)
453 case BpfErrTruncated{len}:
454 "truncated program of " ++ Nat.show(len) ++ " bytes"
455 case BpfErrStoredTooLong{max}:
456 "stored program over " ++ Nat.show(max) ++ " bytes"
457 case BpfErrEmpty{}:
458 "empty program"
459 case BpfErrTooLong{len}:
460 "program too long: " ++ Nat.show(len)
461 case BpfErrJump{pc}:
462 "jump out of range at " ++ Nat.show(pc)
463 case BpfErrJumpField{pc}:
464 "jump offset over 255 at " ++ Nat.show(pc)
465 case BpfErrNoReturn{pc}:
466 "no return after " ++ Nat.show(pc)
467 case BpfErrScratch{pc}:
468 "scratch index out of range at " ++ Nat.show(pc)
469 case BpfErrDivZero{pc}:
470 "division by constant zero at " ++ Nat.show(pc)
471 case BpfErrMemInit{pc}:
472 "scratch read before write at " ++ Nat.show(pc)
473 case BpfErrSeccompLoad{pc}:
474 "load not allowed in seccomp at " ++ Nat.show(pc)
475 case BpfErrSeccompInsn{pc}:
476 "instruction not allowed in seccomp at " ++ Nat.show(pc)
477 case BpfErrPathTooLong{total}:
478 "seccomp filters too long: " ++ Nat.show(total)
479 case BpfErrFellOff{}:
480 "ran past the end"
481 case BpfErrBadScratch{k}:
482 "scratch index " ++ U32.show(k)