root/samples/seccomp/bpf-helper.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /*
   3  * Example wrapper around BPF macros.
   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_SET_SECCOMP, 2, ...).
  11  *
  12  * No guarantees are provided with respect to the correctness
  13  * or functionality of this code.
  14  */
  15 #ifndef __BPF_HELPER_H__
  16 #define __BPF_HELPER_H__
  17 
  18 #include <asm/bitsperlong.h>    /* for __BITS_PER_LONG */
  19 #include <endian.h>
  20 #include <linux/filter.h>
  21 #include <linux/seccomp.h>      /* for seccomp_data */
  22 #include <linux/types.h>
  23 #include <linux/unistd.h>
  24 #include <stddef.h>
  25 
  26 #define BPF_LABELS_MAX 256
  27 struct bpf_labels {
  28         int count;
  29         struct __bpf_label {
  30                 const char *label;
  31                 __u32 location;
  32         } labels[BPF_LABELS_MAX];
  33 };
  34 
  35 int bpf_resolve_jumps(struct bpf_labels *labels,
  36                       struct sock_filter *filter, size_t count);
  37 __u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label);
  38 void seccomp_bpf_print(struct sock_filter *filter, size_t count);
  39 
  40 #define JUMP_JT 0xff
  41 #define JUMP_JF 0xff
  42 #define LABEL_JT 0xfe
  43 #define LABEL_JF 0xfe
  44 
  45 #define ALLOW \
  46         BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
  47 #define DENY \
  48         BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
  49 #define JUMP(labels, label) \
  50         BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  51                  JUMP_JT, JUMP_JF)
  52 #define LABEL(labels, label) \
  53         BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  54                  LABEL_JT, LABEL_JF)
  55 #define SYSCALL(nr, jt) \
  56         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (nr), 0, 1), \
  57         jt
  58 
  59 /* Lame, but just an example */
  60 #define FIND_LABEL(labels, label) seccomp_bpf_label((labels), #label)
  61 
  62 #define EXPAND(...) __VA_ARGS__
  63 
  64 /* Ensure that we load the logically correct offset. */
  65 #if __BYTE_ORDER == __LITTLE_ENDIAN
  66 #define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
  67 #elif __BYTE_ORDER == __BIG_ENDIAN
  68 #define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
  69 #else
  70 #error "Unknown endianness"
  71 #endif
  72 
  73 /* Map all width-sensitive operations */
  74 #if __BITS_PER_LONG == 32
  75 
  76 #define JEQ(x, jt) JEQ32(x, EXPAND(jt))
  77 #define JNE(x, jt) JNE32(x, EXPAND(jt))
  78 #define JGT(x, jt) JGT32(x, EXPAND(jt))
  79 #define JLT(x, jt) JLT32(x, EXPAND(jt))
  80 #define JGE(x, jt) JGE32(x, EXPAND(jt))
  81 #define JLE(x, jt) JLE32(x, EXPAND(jt))
  82 #define JA(x, jt) JA32(x, EXPAND(jt))
  83 #define ARG(i) ARG_32(i)
  84 
  85 #elif __BITS_PER_LONG == 64
  86 
  87 /* Ensure that we load the logically correct offset. */
  88 #if __BYTE_ORDER == __LITTLE_ENDIAN
  89 #define ENDIAN(_lo, _hi) _lo, _hi
  90 #define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
  91 #elif __BYTE_ORDER == __BIG_ENDIAN
  92 #define ENDIAN(_lo, _hi) _hi, _lo
  93 #define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
  94 #endif
  95 
  96 union arg64 {
  97         struct {
  98                 __u32 ENDIAN(lo32, hi32);
  99         };
 100         __u64 u64;
 101 };
 102 
 103 #define JEQ(x, jt) \
 104         JEQ64(((union arg64){.u64 = (x)}).lo32, \
 105               ((union arg64){.u64 = (x)}).hi32, \
 106               EXPAND(jt))
 107 #define JGT(x, jt) \
 108         JGT64(((union arg64){.u64 = (x)}).lo32, \
 109               ((union arg64){.u64 = (x)}).hi32, \
 110               EXPAND(jt))
 111 #define JGE(x, jt) \
 112         JGE64(((union arg64){.u64 = (x)}).lo32, \
 113               ((union arg64){.u64 = (x)}).hi32, \
 114               EXPAND(jt))
 115 #define JNE(x, jt) \
 116         JNE64(((union arg64){.u64 = (x)}).lo32, \
 117               ((union arg64){.u64 = (x)}).hi32, \
 118               EXPAND(jt))
 119 #define JLT(x, jt) \
 120         JLT64(((union arg64){.u64 = (x)}).lo32, \
 121               ((union arg64){.u64 = (x)}).hi32, \
 122               EXPAND(jt))
 123 #define JLE(x, jt) \
 124         JLE64(((union arg64){.u64 = (x)}).lo32, \
 125               ((union arg64){.u64 = (x)}).hi32, \
 126               EXPAND(jt))
 127 
 128 #define JA(x, jt) \
 129         JA64(((union arg64){.u64 = (x)}).lo32, \
 130                ((union arg64){.u64 = (x)}).hi32, \
 131                EXPAND(jt))
 132 #define ARG(i) ARG_64(i)
 133 
 134 #else
 135 #error __BITS_PER_LONG value unusable.
 136 #endif
 137 
 138 /* Loads the arg into A */
 139 #define ARG_32(idx) \
 140         BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx))
 141 
 142 /* Loads lo into M[0] and hi into M[1] and A */
 143 #define ARG_64(idx) \
 144         BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \
 145         BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \
 146         BPF_STMT(BPF_LD+BPF_W+BPF_ABS, HI_ARG(idx)), \
 147         BPF_STMT(BPF_ST, 1) /* hi -> M[1] */
 148 
 149 #define JEQ32(value, jt) \
 150         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 0, 1), \
 151         jt
 152 
 153 #define JNE32(value, jt) \
 154         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \
 155         jt
 156 
 157 #define JA32(value, jt) \
 158         BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
 159         jt
 160 
 161 #define JGE32(value, jt) \
 162         BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
 163         jt
 164 
 165 #define JGT32(value, jt) \
 166         BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
 167         jt
 168 
 169 #define JLE32(value, jt) \
 170         BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
 171         jt
 172 
 173 #define JLT32(value, jt) \
 174         BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
 175         jt
 176 
 177 /*
 178  * All the JXX64 checks assume lo is saved in M[0] and hi is saved in both
 179  * A and M[1]. This invariant is kept by restoring A if necessary.
 180  */
 181 #define JEQ64(lo, hi, jt) \
 182         /* if (hi != arg.hi) goto NOMATCH; */ \
 183         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
 184         BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
 185         /* if (lo != arg.lo) goto NOMATCH; */ \
 186         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \
 187         BPF_STMT(BPF_LD+BPF_MEM, 1), \
 188         jt, \
 189         BPF_STMT(BPF_LD+BPF_MEM, 1)
 190 
 191 #define JNE64(lo, hi, jt) \
 192         /* if (hi != arg.hi) goto MATCH; */ \
 193         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
 194         BPF_STMT(BPF_LD+BPF_MEM, 0), \
 195         /* if (lo != arg.lo) goto MATCH; */ \
 196         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \
 197         BPF_STMT(BPF_LD+BPF_MEM, 1), \
 198         jt, \
 199         BPF_STMT(BPF_LD+BPF_MEM, 1)
 200 
 201 #define JA64(lo, hi, jt) \
 202         /* if (hi & arg.hi) goto MATCH; */ \
 203         BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \
 204         BPF_STMT(BPF_LD+BPF_MEM, 0), \
 205         /* if (lo & arg.lo) goto MATCH; */ \
 206         BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \
 207         BPF_STMT(BPF_LD+BPF_MEM, 1), \
 208         jt, \
 209         BPF_STMT(BPF_LD+BPF_MEM, 1)
 210 
 211 #define JGE64(lo, hi, jt) \
 212         /* if (hi > arg.hi) goto MATCH; */ \
 213         BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
 214         /* if (hi != arg.hi) goto NOMATCH; */ \
 215         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
 216         BPF_STMT(BPF_LD+BPF_MEM, 0), \
 217         /* if (lo >= arg.lo) goto MATCH; */ \
 218         BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \
 219         BPF_STMT(BPF_LD+BPF_MEM, 1), \
 220         jt, \
 221         BPF_STMT(BPF_LD+BPF_MEM, 1)
 222 
 223 #define JGT64(lo, hi, jt) \
 224         /* if (hi > arg.hi) goto MATCH; */ \
 225         BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
 226         /* if (hi != arg.hi) goto NOMATCH; */ \
 227         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
 228         BPF_STMT(BPF_LD+BPF_MEM, 0), \
 229         /* if (lo > arg.lo) goto MATCH; */ \
 230         BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \
 231         BPF_STMT(BPF_LD+BPF_MEM, 1), \
 232         jt, \
 233         BPF_STMT(BPF_LD+BPF_MEM, 1)
 234 
 235 #define JLE64(lo, hi, jt) \
 236         /* if (hi < arg.hi) goto MATCH; */ \
 237         BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
 238         /* if (hi != arg.hi) goto NOMATCH; */ \
 239         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
 240         BPF_STMT(BPF_LD+BPF_MEM, 0), \
 241         /* if (lo <= arg.lo) goto MATCH; */ \
 242         BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
 243         BPF_STMT(BPF_LD+BPF_MEM, 1), \
 244         jt, \
 245         BPF_STMT(BPF_LD+BPF_MEM, 1)
 246 
 247 #define JLT64(lo, hi, jt) \
 248         /* if (hi < arg.hi) goto MATCH; */ \
 249         BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
 250         /* if (hi != arg.hi) goto NOMATCH; */ \
 251         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
 252         BPF_STMT(BPF_LD+BPF_MEM, 0), \
 253         /* if (lo < arg.lo) goto MATCH; */ \
 254         BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 2, 0), \
 255         BPF_STMT(BPF_LD+BPF_MEM, 1), \
 256         jt, \
 257         BPF_STMT(BPF_LD+BPF_MEM, 1)
 258 
 259 #define LOAD_SYSCALL_NR \
 260         BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
 261                  offsetof(struct seccomp_data, nr))
 262 
 263 #endif  /* __BPF_HELPER_H__ */

/* [<][>][^][v][top][bottom][index][help] */