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, "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, "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, "Too many labels\n"); 71 exit(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(label, 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("{ code=%u,jt=%u,jf=%u,k=%u },\n", 95 filter->code, filter->jt, filter->jf, filter->k); 96 } 97