162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Seccomp BPF helper functions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org> 662306a36Sopenharmony_ci * Author: Will Drewry <wad@chromium.org> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * The code may be used by anyone for any purpose, 962306a36Sopenharmony_ci * and can serve as a starting point for developing 1062306a36Sopenharmony_ci * applications using prctl(PR_ATTACH_SECCOMP_FILTER). 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <stdio.h> 1462306a36Sopenharmony_ci#include <stdlib.h> 1562306a36Sopenharmony_ci#include <string.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "bpf-helper.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciint bpf_resolve_jumps(struct bpf_labels *labels, 2062306a36Sopenharmony_ci struct sock_filter *filter, size_t count) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci size_t i; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci if (count < 1 || count > BPF_MAXINSNS) 2562306a36Sopenharmony_ci return -1; 2662306a36Sopenharmony_ci /* 2762306a36Sopenharmony_ci * Walk it once, backwards, to build the label table and do fixups. 2862306a36Sopenharmony_ci * Since backward jumps are disallowed by BPF, this is easy. 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci for (i = 0; i < count; ++i) { 3162306a36Sopenharmony_ci size_t offset = count - i - 1; 3262306a36Sopenharmony_ci struct sock_filter *instr = &filter[offset]; 3362306a36Sopenharmony_ci if (instr->code != (BPF_JMP+BPF_JA)) 3462306a36Sopenharmony_ci continue; 3562306a36Sopenharmony_ci switch ((instr->jt<<8)|instr->jf) { 3662306a36Sopenharmony_ci case (JUMP_JT<<8)|JUMP_JF: 3762306a36Sopenharmony_ci if (labels->labels[instr->k].location == 0xffffffff) { 3862306a36Sopenharmony_ci fprintf(stderr, "Unresolved label: '%s'\n", 3962306a36Sopenharmony_ci labels->labels[instr->k].label); 4062306a36Sopenharmony_ci return 1; 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci instr->k = labels->labels[instr->k].location - 4362306a36Sopenharmony_ci (offset + 1); 4462306a36Sopenharmony_ci instr->jt = 0; 4562306a36Sopenharmony_ci instr->jf = 0; 4662306a36Sopenharmony_ci continue; 4762306a36Sopenharmony_ci case (LABEL_JT<<8)|LABEL_JF: 4862306a36Sopenharmony_ci if (labels->labels[instr->k].location != 0xffffffff) { 4962306a36Sopenharmony_ci fprintf(stderr, "Duplicate label use: '%s'\n", 5062306a36Sopenharmony_ci labels->labels[instr->k].label); 5162306a36Sopenharmony_ci return 1; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci labels->labels[instr->k].location = offset; 5462306a36Sopenharmony_ci instr->k = 0; /* fall through */ 5562306a36Sopenharmony_ci instr->jt = 0; 5662306a36Sopenharmony_ci instr->jf = 0; 5762306a36Sopenharmony_ci continue; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci return 0; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* Simple lookup table for labels. */ 6462306a36Sopenharmony_ci__u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct __bpf_label *begin = labels->labels, *end; 6762306a36Sopenharmony_ci int id; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci if (labels->count == BPF_LABELS_MAX) { 7062306a36Sopenharmony_ci fprintf(stderr, "Too many labels\n"); 7162306a36Sopenharmony_ci exit(1); 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ci if (labels->count == 0) { 7462306a36Sopenharmony_ci begin->label = label; 7562306a36Sopenharmony_ci begin->location = 0xffffffff; 7662306a36Sopenharmony_ci labels->count++; 7762306a36Sopenharmony_ci return 0; 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci end = begin + labels->count; 8062306a36Sopenharmony_ci for (id = 0; begin < end; ++begin, ++id) { 8162306a36Sopenharmony_ci if (!strcmp(label, begin->label)) 8262306a36Sopenharmony_ci return id; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci begin->label = label; 8562306a36Sopenharmony_ci begin->location = 0xffffffff; 8662306a36Sopenharmony_ci labels->count++; 8762306a36Sopenharmony_ci return id; 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_civoid seccomp_bpf_print(struct sock_filter *filter, size_t count) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci struct sock_filter *end = filter + count; 9362306a36Sopenharmony_ci for ( ; filter < end; ++filter) 9462306a36Sopenharmony_ci printf("{ code=%u,jt=%u,jf=%u,k=%u },\n", 9562306a36Sopenharmony_ci filter->code, filter->jt, filter->jf, filter->k); 9662306a36Sopenharmony_ci} 97