18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Seccomp BPF helper functions 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org> 68c2ecf20Sopenharmony_ci * Author: Will Drewry <wad@chromium.org> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * The code may be used by anyone for any purpose, 98c2ecf20Sopenharmony_ci * and can serve as a starting point for developing 108c2ecf20Sopenharmony_ci * applications using prctl(PR_ATTACH_SECCOMP_FILTER). 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <stdio.h> 148c2ecf20Sopenharmony_ci#include <stdlib.h> 158c2ecf20Sopenharmony_ci#include <string.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "bpf-helper.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciint bpf_resolve_jumps(struct bpf_labels *labels, 208c2ecf20Sopenharmony_ci struct sock_filter *filter, size_t count) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci size_t i; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci if (count < 1 || count > BPF_MAXINSNS) 258c2ecf20Sopenharmony_ci return -1; 268c2ecf20Sopenharmony_ci /* 278c2ecf20Sopenharmony_ci * Walk it once, backwards, to build the label table and do fixups. 288c2ecf20Sopenharmony_ci * Since backward jumps are disallowed by BPF, this is easy. 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci for (i = 0; i < count; ++i) { 318c2ecf20Sopenharmony_ci size_t offset = count - i - 1; 328c2ecf20Sopenharmony_ci struct sock_filter *instr = &filter[offset]; 338c2ecf20Sopenharmony_ci if (instr->code != (BPF_JMP+BPF_JA)) 348c2ecf20Sopenharmony_ci continue; 358c2ecf20Sopenharmony_ci switch ((instr->jt<<8)|instr->jf) { 368c2ecf20Sopenharmony_ci case (JUMP_JT<<8)|JUMP_JF: 378c2ecf20Sopenharmony_ci if (labels->labels[instr->k].location == 0xffffffff) { 388c2ecf20Sopenharmony_ci fprintf(stderr, "Unresolved label: '%s'\n", 398c2ecf20Sopenharmony_ci labels->labels[instr->k].label); 408c2ecf20Sopenharmony_ci return 1; 418c2ecf20Sopenharmony_ci } 428c2ecf20Sopenharmony_ci instr->k = labels->labels[instr->k].location - 438c2ecf20Sopenharmony_ci (offset + 1); 448c2ecf20Sopenharmony_ci instr->jt = 0; 458c2ecf20Sopenharmony_ci instr->jf = 0; 468c2ecf20Sopenharmony_ci continue; 478c2ecf20Sopenharmony_ci case (LABEL_JT<<8)|LABEL_JF: 488c2ecf20Sopenharmony_ci if (labels->labels[instr->k].location != 0xffffffff) { 498c2ecf20Sopenharmony_ci fprintf(stderr, "Duplicate label use: '%s'\n", 508c2ecf20Sopenharmony_ci labels->labels[instr->k].label); 518c2ecf20Sopenharmony_ci return 1; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci labels->labels[instr->k].location = offset; 548c2ecf20Sopenharmony_ci instr->k = 0; /* fall through */ 558c2ecf20Sopenharmony_ci instr->jt = 0; 568c2ecf20Sopenharmony_ci instr->jf = 0; 578c2ecf20Sopenharmony_ci continue; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci return 0; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* Simple lookup table for labels. */ 648c2ecf20Sopenharmony_ci__u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci struct __bpf_label *begin = labels->labels, *end; 678c2ecf20Sopenharmony_ci int id; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (labels->count == BPF_LABELS_MAX) { 708c2ecf20Sopenharmony_ci fprintf(stderr, "Too many labels\n"); 718c2ecf20Sopenharmony_ci exit(1); 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci if (labels->count == 0) { 748c2ecf20Sopenharmony_ci begin->label = label; 758c2ecf20Sopenharmony_ci begin->location = 0xffffffff; 768c2ecf20Sopenharmony_ci labels->count++; 778c2ecf20Sopenharmony_ci return 0; 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci end = begin + labels->count; 808c2ecf20Sopenharmony_ci for (id = 0; begin < end; ++begin, ++id) { 818c2ecf20Sopenharmony_ci if (!strcmp(label, begin->label)) 828c2ecf20Sopenharmony_ci return id; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci begin->label = label; 858c2ecf20Sopenharmony_ci begin->location = 0xffffffff; 868c2ecf20Sopenharmony_ci labels->count++; 878c2ecf20Sopenharmony_ci return id; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_civoid seccomp_bpf_print(struct sock_filter *filter, size_t count) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct sock_filter *end = filter + count; 938c2ecf20Sopenharmony_ci for ( ; filter < end; ++filter) 948c2ecf20Sopenharmony_ci printf("{ code=%u,jt=%u,jf=%u,k=%u },\n", 958c2ecf20Sopenharmony_ci filter->code, filter->jt, filter->jf, filter->k); 968c2ecf20Sopenharmony_ci} 97