1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Seccomp BPF helper functions |
4 | * |
5 | * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org> |
6 | * Author: Will Drewry <wad@chromium.org> |
7 | * |
8 | * The code may be used by anyone for any purpose, |
9 | * and can serve as a starting point for developing |
10 | * applications using prctl(PR_ATTACH_SECCOMP_FILTER). |
11 | */ |
12 | |
13 | #include <stdio.h> |
14 | #include <stdlib.h> |
15 | #include <string.h> |
16 | |
17 | #include "bpf-helper.h" |
18 | |
19 | int bpf_resolve_jumps(struct bpf_labels *labels, |
20 | struct sock_filter *filter, size_t count) |
21 | { |
22 | size_t i; |
23 | |
24 | if (count < 1 || count > BPF_MAXINSNS) |
25 | return -1; |
26 | /* |
27 | * Walk it once, backwards, to build the label table and do fixups. |
28 | * Since backward jumps are disallowed by BPF, this is easy. |
29 | */ |
30 | for (i = 0; i < count; ++i) { |
31 | size_t offset = count - i - 1; |
32 | struct sock_filter *instr = &filter[offset]; |
33 | if (instr->code != (BPF_JMP+BPF_JA)) |
34 | continue; |
35 | switch ((instr->jt<<8)|instr->jf) { |
36 | case (JUMP_JT<<8)|JUMP_JF: |
37 | if (labels->labels[instr->k].location == 0xffffffff) { |
38 | fprintf(stderr, format: "Unresolved label: '%s'\n" , |
39 | labels->labels[instr->k].label); |
40 | return 1; |
41 | } |
42 | instr->k = labels->labels[instr->k].location - |
43 | (offset + 1); |
44 | instr->jt = 0; |
45 | instr->jf = 0; |
46 | continue; |
47 | case (LABEL_JT<<8)|LABEL_JF: |
48 | if (labels->labels[instr->k].location != 0xffffffff) { |
49 | fprintf(stderr, format: "Duplicate label use: '%s'\n" , |
50 | labels->labels[instr->k].label); |
51 | return 1; |
52 | } |
53 | labels->labels[instr->k].location = offset; |
54 | instr->k = 0; /* fall through */ |
55 | instr->jt = 0; |
56 | instr->jf = 0; |
57 | continue; |
58 | } |
59 | } |
60 | return 0; |
61 | } |
62 | |
63 | /* Simple lookup table for labels. */ |
64 | __u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label) |
65 | { |
66 | struct __bpf_label *begin = labels->labels, *end; |
67 | int id; |
68 | |
69 | if (labels->count == BPF_LABELS_MAX) { |
70 | fprintf(stderr, format: "Too many labels\n" ); |
71 | exit(status: 1); |
72 | } |
73 | if (labels->count == 0) { |
74 | begin->label = label; |
75 | begin->location = 0xffffffff; |
76 | labels->count++; |
77 | return 0; |
78 | } |
79 | end = begin + labels->count; |
80 | for (id = 0; begin < end; ++begin, ++id) { |
81 | if (!strcmp(s1: label, s2: begin->label)) |
82 | return id; |
83 | } |
84 | begin->label = label; |
85 | begin->location = 0xffffffff; |
86 | labels->count++; |
87 | return id; |
88 | } |
89 | |
90 | void seccomp_bpf_print(struct sock_filter *filter, size_t count) |
91 | { |
92 | struct sock_filter *end = filter + count; |
93 | for ( ; filter < end; ++filter) |
94 | printf(format: "{ code=%u,jt=%u,jf=%u,k=%u },\n" , |
95 | filter->code, filter->jt, filter->jf, filter->k); |
96 | } |
97 | |