Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / samples / seccomp / bpf-helper.h
diff --git a/kernel/samples/seccomp/bpf-helper.h b/kernel/samples/seccomp/bpf-helper.h
new file mode 100644 (file)
index 0000000..38ee70f
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Example wrapper around BPF macros.
+ *
+ * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
+ * Author: Will Drewry <wad@chromium.org>
+ *
+ * The code may be used by anyone for any purpose,
+ * and can serve as a starting point for developing
+ * applications using prctl(PR_SET_SECCOMP, 2, ...).
+ *
+ * No guarantees are provided with respect to the correctness
+ * or functionality of this code.
+ */
+#ifndef __BPF_HELPER_H__
+#define __BPF_HELPER_H__
+
+#include <asm/bitsperlong.h>   /* for __BITS_PER_LONG */
+#include <endian.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>     /* for seccomp_data */
+#include <linux/types.h>
+#include <linux/unistd.h>
+#include <stddef.h>
+
+#define BPF_LABELS_MAX 256
+struct bpf_labels {
+       int count;
+       struct __bpf_label {
+               const char *label;
+               __u32 location;
+       } labels[BPF_LABELS_MAX];
+};
+
+int bpf_resolve_jumps(struct bpf_labels *labels,
+                     struct sock_filter *filter, size_t count);
+__u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label);
+void seccomp_bpf_print(struct sock_filter *filter, size_t count);
+
+#define JUMP_JT 0xff
+#define JUMP_JF 0xff
+#define LABEL_JT 0xfe
+#define LABEL_JF 0xfe
+
+#define ALLOW \
+       BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
+#define DENY \
+       BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
+#define JUMP(labels, label) \
+       BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
+                JUMP_JT, JUMP_JF)
+#define LABEL(labels, label) \
+       BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
+                LABEL_JT, LABEL_JF)
+#define SYSCALL(nr, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (nr), 0, 1), \
+       jt
+
+/* Lame, but just an example */
+#define FIND_LABEL(labels, label) seccomp_bpf_label((labels), #label)
+
+#define EXPAND(...) __VA_ARGS__
+
+/* Ensure that we load the logically correct offset. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
+#else
+#error "Unknown endianness"
+#endif
+
+/* Map all width-sensitive operations */
+#if __BITS_PER_LONG == 32
+
+#define JEQ(x, jt) JEQ32(x, EXPAND(jt))
+#define JNE(x, jt) JNE32(x, EXPAND(jt))
+#define JGT(x, jt) JGT32(x, EXPAND(jt))
+#define JLT(x, jt) JLT32(x, EXPAND(jt))
+#define JGE(x, jt) JGE32(x, EXPAND(jt))
+#define JLE(x, jt) JLE32(x, EXPAND(jt))
+#define JA(x, jt) JA32(x, EXPAND(jt))
+#define ARG(i) ARG_32(i)
+
+#elif __BITS_PER_LONG == 64
+
+/* Ensure that we load the logically correct offset. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define ENDIAN(_lo, _hi) _lo, _hi
+#define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define ENDIAN(_lo, _hi) _hi, _lo
+#define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
+#endif
+
+union arg64 {
+       struct {
+               __u32 ENDIAN(lo32, hi32);
+       };
+       __u64 u64;
+};
+
+#define JEQ(x, jt) \
+       JEQ64(((union arg64){.u64 = (x)}).lo32, \
+             ((union arg64){.u64 = (x)}).hi32, \
+             EXPAND(jt))
+#define JGT(x, jt) \
+       JGT64(((union arg64){.u64 = (x)}).lo32, \
+             ((union arg64){.u64 = (x)}).hi32, \
+             EXPAND(jt))
+#define JGE(x, jt) \
+       JGE64(((union arg64){.u64 = (x)}).lo32, \
+             ((union arg64){.u64 = (x)}).hi32, \
+             EXPAND(jt))
+#define JNE(x, jt) \
+       JNE64(((union arg64){.u64 = (x)}).lo32, \
+             ((union arg64){.u64 = (x)}).hi32, \
+             EXPAND(jt))
+#define JLT(x, jt) \
+       JLT64(((union arg64){.u64 = (x)}).lo32, \
+             ((union arg64){.u64 = (x)}).hi32, \
+             EXPAND(jt))
+#define JLE(x, jt) \
+       JLE64(((union arg64){.u64 = (x)}).lo32, \
+             ((union arg64){.u64 = (x)}).hi32, \
+             EXPAND(jt))
+
+#define JA(x, jt) \
+       JA64(((union arg64){.u64 = (x)}).lo32, \
+              ((union arg64){.u64 = (x)}).hi32, \
+              EXPAND(jt))
+#define ARG(i) ARG_64(i)
+
+#else
+#error __BITS_PER_LONG value unusable.
+#endif
+
+/* Loads the arg into A */
+#define ARG_32(idx) \
+       BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx))
+
+/* Loads hi into A and lo in X */
+#define ARG_64(idx) \
+       BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \
+       BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \
+       BPF_STMT(BPF_LD+BPF_W+BPF_ABS, HI_ARG(idx)), \
+       BPF_STMT(BPF_ST, 1) /* hi -> M[1] */
+
+#define JEQ32(value, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 0, 1), \
+       jt
+
+#define JNE32(value, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \
+       jt
+
+/* Checks the lo, then swaps to check the hi. A=lo,X=hi */
+#define JEQ64(lo, hi, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+       BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \
+       BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+       jt, \
+       BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JNE64(lo, hi, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 5, 0), \
+       BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \
+       BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+       jt, \
+       BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JA32(value, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
+       jt
+
+#define JA64(lo, hi, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \
+       BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+       BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \
+       BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+       jt, \
+       BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JGE32(value, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
+       jt
+
+#define JLT32(value, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
+       jt
+
+/* Shortcut checking if hi > arg.hi. */
+#define JGE64(lo, hi, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+       BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+       BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \
+       BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+       jt, \
+       BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JLT64(lo, hi, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+       BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+       BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
+       BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+       jt, \
+       BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JGT32(value, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
+       jt
+
+#define JLE32(value, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
+       jt
+
+/* Check hi > args.hi first, then do the GE checking */
+#define JGT64(lo, hi, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+       BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+       BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \
+       BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+       jt, \
+       BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define JLE64(lo, hi, jt) \
+       BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 6, 0), \
+       BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
+       BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+       BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
+       BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+       jt, \
+       BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+
+#define LOAD_SYSCALL_NR \
+       BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
+                offsetof(struct seccomp_data, nr))
+
+#endif  /* __BPF_HELPER_H__ */