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