int main(void) { int small_map = array_create(8, 1); struct bpf_insn insns[] = { // load NULL pointer, tracked as "NULL or value pointer", into r0 BPF_LD_MAP_FD(BPF_REG_ARG1, small_map), BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP), BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -4), BPF_ST_MEM(BPF_W, BPF_REG_ARG2, 0, 9), //oob index BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // compute r9 = laundered_frame_pointer BPF_MOV64_REG(BPF_REG_9, BPF_REG_FP), BPF_ALU64_REG(BPF_SUB, BPF_REG_9, BPF_REG_0), // store r9 into map BPF_LD_MAP_FD(BPF_REG_ARG1, small_map), BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP), BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -4), BPF_ST_MEM(BPF_W, BPF_REG_ARG2, 0, 0), BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(), BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_9, 0), BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN() }; int sock_fd = create_filtered_socket_fd(insns, ARRSIZE(insns)); trigger_proc(sock_fd); printf("leaked pointer: 0x%lx\n", array_get_dw(small_map, 0)); }
static int check_env(void) { int err; unsigned int kver_int; char license[] = "GPL"; struct bpf_insn insns[] = { BPF_MOV64_IMM(BPF_REG_0, 1), BPF_EXIT_INSN(), }; err = fetch_kernel_version(&kver_int, NULL, 0); if (err) { pr_debug("Unable to get kernel version\n"); return err; } err = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, sizeof(insns) / sizeof(insns[0]), license, kver_int, NULL, 0); if (err < 0) { pr_err("Missing basic BPF support, skip this test: %s\n", strerror(errno)); return err; } close(err); return 0; }
static void bpf_gen_imm_prog(unsigned int insns, int fd_map) { int i; srand(time(NULL)); for (i = 0; i < insns; i++) prog[i] = BPF_ALU64_IMM(BPF_MOV, i % BPF_REG_10, rand()); prog[i - 1] = BPF_EXIT_INSN(); }
static void bpf_gen_map_prog(unsigned int insns, int fd_map) { int i, j = 0; for (i = 0; i + 1 < insns; i += 2) { struct bpf_insn tmp[] = { BPF_LD_MAP_FD(j++ % BPF_REG_10, fd_map) }; memcpy(&prog[i], tmp, sizeof(tmp)); } if (insns % 2 == 0) prog[insns - 2] = BPF_ALU64_IMM(BPF_MOV, i % BPF_REG_10, 42); prog[insns - 1] = BPF_EXIT_INSN(); }
static int bpf_prog_create(const char *object) { static struct bpf_insn insns[] = { BPF_MOV64_IMM(BPF_REG_0, 1), BPF_EXIT_INSN(), }; size_t insns_cnt = sizeof(insns) / sizeof(struct bpf_insn); if (object) { assert(!load_bpf_file((char *)object)); return prog_fd[0]; } else { return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, insns, insns_cnt, "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE); } }
static int prog_load(int verdict) { int ret; struct bpf_insn prog[] = { BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ BPF_EXIT_INSN(), }; size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, prog, insns_cnt, "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE); if (ret < 0) { log_err("Loading program"); printf("Output from verifier:\n%s\n-------\n", bpf_log_buf); return 0; } return ret; }
void test_raw_tp_writable_reject_nbd_invalid(void) { __u32 duration = 0; char error[4096]; int bpf_fd = -1, tp_fd = -1; const struct bpf_insn program[] = { /* r6 is our tp buffer */ BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* one byte beyond the end of the nbd_request struct */ BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_6, sizeof(struct nbd_request)), BPF_EXIT_INSN(), }; struct bpf_load_program_attr load_attr = { .prog_type = BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, .license = "GPL v2", .insns = program, .insns_cnt = sizeof(program) / sizeof(struct bpf_insn), .log_level = 2, }; bpf_fd = bpf_load_program_xattr(&load_attr, error, sizeof(error)); if (CHECK(bpf_fd < 0, "bpf_raw_tracepoint_writable load", "failed: %d errno %d\n", bpf_fd, errno)) return; tp_fd = bpf_raw_tracepoint_open("nbd_send_request", bpf_fd); if (CHECK(tp_fd >= 0, "bpf_raw_tracepoint_writable open", "erroneously succeeded\n")) goto out_bpffd; close(tp_fd); out_bpffd: close(bpf_fd); }
static int prog_load_cnt(int verdict, int val) { int cgroup_storage_fd, percpu_cgroup_storage_fd; if (map_fd < 0) map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, 4, 8, 1, 0); if (map_fd < 0) { printf("failed to create map '%s'\n", strerror(errno)); return -1; } cgroup_storage_fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_STORAGE, sizeof(struct bpf_cgroup_storage_key), 8, 0, 0); if (cgroup_storage_fd < 0) { printf("failed to create map '%s'\n", strerror(errno)); return -1; } percpu_cgroup_storage_fd = bpf_create_map( BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE, sizeof(struct bpf_cgroup_storage_key), 8, 0, 0); if (percpu_cgroup_storage_fd < 0) { printf("failed to create map '%s'\n", strerror(errno)); return -1; } struct bpf_insn prog[] = { BPF_MOV32_IMM(BPF_REG_0, 0), BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ BPF_LD_MAP_FD(BPF_REG_1, map_fd), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), BPF_MOV64_IMM(BPF_REG_1, val), /* r1 = 1 */ BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */ BPF_LD_MAP_FD(BPF_REG_1, cgroup_storage_fd), BPF_MOV64_IMM(BPF_REG_2, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_local_storage), BPF_MOV64_IMM(BPF_REG_1, val), BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_W, BPF_REG_0, BPF_REG_1, 0, 0), BPF_LD_MAP_FD(BPF_REG_1, percpu_cgroup_storage_fd), BPF_MOV64_IMM(BPF_REG_2, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_local_storage), BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0), BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 0x1), BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_3, 0), BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ BPF_EXIT_INSN(), }; size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); int ret; ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, prog, insns_cnt, "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE); if (ret < 0) { log_err("Loading program"); printf("Output from verifier:\n%s\n-------\n", bpf_log_buf); return 0; } close(cgroup_storage_fd); return ret; }
static bool convert_bpf_extensions(struct sock_filter *fp, struct bpf_insn **insnp) { struct bpf_insn *insn = *insnp; switch (fp->k) { case SKF_AD_OFF + SKF_AD_PROTOCOL: BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2); /* A = *(u16 *) (CTX + offsetof(protocol)) */ *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX, offsetof(struct sk_buff, protocol)); /* A = ntohs(A) [emitting a nop or swap16] */ *insn = BPF_ENDIAN(BPF_FROM_BE, BPF_REG_A, 16); break; case SKF_AD_OFF + SKF_AD_PKTTYPE: *insn++ = BPF_LDX_MEM(BPF_B, BPF_REG_A, BPF_REG_CTX, PKT_TYPE_OFFSET()); *insn = BPF_ALU32_IMM(BPF_AND, BPF_REG_A, PKT_TYPE_MAX); #ifdef __BIG_ENDIAN_BITFIELD insn++; *insn = BPF_ALU32_IMM(BPF_RSH, BPF_REG_A, 5); #endif break; case SKF_AD_OFF + SKF_AD_IFINDEX: case SKF_AD_OFF + SKF_AD_HATYPE: BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4); BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2); BUILD_BUG_ON(bytes_to_bpf_size(FIELD_SIZEOF(struct sk_buff, dev)) < 0); *insn++ = BPF_LDX_MEM(bytes_to_bpf_size(FIELD_SIZEOF(struct sk_buff, dev)), BPF_REG_TMP, BPF_REG_CTX, offsetof(struct sk_buff, dev)); /* if (tmp != 0) goto pc + 1 */ *insn++ = BPF_JMP_IMM(BPF_JNE, BPF_REG_TMP, 0, 1); *insn++ = BPF_EXIT_INSN(); if (fp->k == SKF_AD_OFF + SKF_AD_IFINDEX) *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_TMP, offsetof(struct net_device, ifindex)); else *insn = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_TMP, offsetof(struct net_device, type)); break; case SKF_AD_OFF + SKF_AD_MARK: BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_CTX, offsetof(struct sk_buff, mark)); break; case SKF_AD_OFF + SKF_AD_RXHASH: BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4); *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_CTX, offsetof(struct sk_buff, hash)); break; case SKF_AD_OFF + SKF_AD_QUEUE: BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2); *insn = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX, offsetof(struct sk_buff, queue_mapping)); break; case SKF_AD_OFF + SKF_AD_VLAN_TAG: case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT: BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2); BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000); /* A = *(u16 *) (CTX + offsetof(vlan_tci)) */ *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX, offsetof(struct sk_buff, vlan_tci)); if (fp->k == SKF_AD_OFF + SKF_AD_VLAN_TAG) { *insn = BPF_ALU32_IMM(BPF_AND, BPF_REG_A, ~VLAN_TAG_PRESENT); } else { /* A >>= 12 */ *insn++ = BPF_ALU32_IMM(BPF_RSH, BPF_REG_A, 12); /* A &= 1 */ *insn = BPF_ALU32_IMM(BPF_AND, BPF_REG_A, 1); } break; case SKF_AD_OFF + SKF_AD_PAY_OFFSET: case SKF_AD_OFF + SKF_AD_NLATTR: case SKF_AD_OFF + SKF_AD_NLATTR_NEST: case SKF_AD_OFF + SKF_AD_CPU: case SKF_AD_OFF + SKF_AD_RANDOM: /* arg1 = CTX */ *insn++ = BPF_MOV64_REG(BPF_REG_ARG1, BPF_REG_CTX); /* arg2 = A */ *insn++ = BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_A); /* arg3 = X */ *insn++ = BPF_MOV64_REG(BPF_REG_ARG3, BPF_REG_X); /* Emit call(arg1=CTX, arg2=A, arg3=X) */ switch (fp->k) { case SKF_AD_OFF + SKF_AD_PAY_OFFSET: *insn = BPF_EMIT_CALL(__skb_get_pay_offset); break; case SKF_AD_OFF + SKF_AD_NLATTR: *insn = BPF_EMIT_CALL(__skb_get_nlattr); break; case SKF_AD_OFF + SKF_AD_NLATTR_NEST: *insn = BPF_EMIT_CALL(__skb_get_nlattr_nest); break; case SKF_AD_OFF + SKF_AD_CPU: *insn = BPF_EMIT_CALL(__get_raw_cpu_id); break; case SKF_AD_OFF + SKF_AD_RANDOM: *insn = BPF_EMIT_CALL(__get_random_u32); break; } break; case SKF_AD_OFF + SKF_AD_ALU_XOR_X: /* A ^= X */ *insn = BPF_ALU32_REG(BPF_XOR, BPF_REG_A, BPF_REG_X); break; default: /* This is just a dummy call to avoid letting the compiler * evict __bpf_call_base() as an optimization. Placed here * where no-one bothers. */ BUG_ON(__bpf_call_base(0, 0, 0, 0, 0) != 0); return false; }
int bpf_prog_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, int prog_len, const char *license, int kern_version) { union bpf_attr attr = { .prog_type = prog_type, .insns = ptr_to_u64((void *) insns), .insn_cnt = prog_len / sizeof(struct bpf_insn), .license = ptr_to_u64((void *) license), .log_buf = ptr_to_u64(bpf_log_buf), .log_size = LOG_BUF_SIZE, .log_level = 1, }; attr.kern_version = kern_version; bpf_log_buf[0] = 0; return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); } int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries, int map_flags) { union bpf_attr attr = { .map_type = map_type, .key_size = key_size, .value_size = value_size, .max_entries = max_entries }; return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr)); } int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags) { union bpf_attr attr = { .map_fd = fd, .key = ptr_to_u64(key), .value = ptr_to_u64(value), .flags = flags, }; return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); } int bpf_lookup_elem(int fd, void *key, void *value) { union bpf_attr attr = { .map_fd = fd, .key = ptr_to_u64(key), .value = ptr_to_u64(value), }; return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); } #define BPF_ALU64_IMM(OP, DST, IMM) \ ((struct bpf_insn) { \ .code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = 0, \ .imm = IMM }) #define BPF_MOV64_REG(DST, SRC) \ ((struct bpf_insn) { \ .code = BPF_ALU64 | BPF_MOV | BPF_X, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = 0 }) #define BPF_MOV32_REG(DST, SRC) \ ((struct bpf_insn) { \ .code = BPF_ALU | BPF_MOV | BPF_X, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = 0 }) #define BPF_MOV64_IMM(DST, IMM) \ ((struct bpf_insn) { \ .code = BPF_ALU64 | BPF_MOV | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = 0, \ .imm = IMM }) #define BPF_MOV32_IMM(DST, IMM) \ ((struct bpf_insn) { \ .code = BPF_ALU | BPF_MOV | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = 0, \ .imm = IMM }) #define BPF_LD_IMM64(DST, IMM) \ BPF_LD_IMM64_RAW(DST, 0, IMM) #define BPF_LD_IMM64_RAW(DST, SRC, IMM) \ ((struct bpf_insn) { \ .code = BPF_LD | BPF_DW | BPF_IMM, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = (__u32) (IMM) }), \ ((struct bpf_insn) { \ .code = 0, \ .dst_reg = 0, \ .src_reg = 0, \ .off = 0, \ .imm = ((__u64) (IMM)) >> 32 }) #ifndef BPF_PSEUDO_MAP_FD # define BPF_PSEUDO_MAP_FD 1 #endif #define BPF_LD_MAP_FD(DST, MAP_FD) \ BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD) #define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \ ((struct bpf_insn) { \ .code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ .imm = 0 }) #define BPF_STX_MEM(SIZE, DST, SRC, OFF) \ ((struct bpf_insn) { \ .code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ .imm = 0 }) #define BPF_ST_MEM(SIZE, DST, OFF, IMM) \ ((struct bpf_insn) { \ .code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \ .dst_reg = DST, \ .src_reg = 0, \ .off = OFF, \ .imm = IMM }) #define BPF_JMP_IMM(OP, DST, IMM, OFF) \ ((struct bpf_insn) { \ .code = BPF_JMP | BPF_OP(OP) | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = OFF, \ .imm = IMM }) #define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \ ((struct bpf_insn) { \ .code = CODE, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ .imm = IMM }) #define BPF_EXIT_INSN() \ ((struct bpf_insn) { \ .code = BPF_JMP | BPF_EXIT, \ .dst_reg = 0, \ .src_reg = 0, \ .off = 0, \ .imm = 0 }) #define BPF_DISABLE_VERIFIER() \ BPF_MOV32_IMM(BPF_REG_2, 0xFFFFFFFF), /* r2 = (u32)0xFFFFFFFF */ \ BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0xFFFFFFFF, 2), /* if (r2 == -1) { */ \ BPF_MOV64_IMM(BPF_REG_0, 0), /* exit(0); */ \ BPF_EXIT_INSN() /* } */ \ #define BPF_MAP_GET(idx, dst) \ BPF_MOV64_REG(BPF_REG_1, BPF_REG_9), /* r1 = r9 */ \ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), /* r2 = fp */ \ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ \ BPF_ST_MEM(BPF_W, BPF_REG_10, -4, idx), /* *(u32 *)(fp - 4) = idx */ \ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), \ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), /* if (r0 == 0) */ \ BPF_EXIT_INSN(), /* exit(0); */ \ BPF_LDX_MEM(BPF_DW, (dst), BPF_REG_0, 0) /* r_dst = *(u64 *)(r0) */ static int load_prog() { struct bpf_insn prog[] = { BPF_DISABLE_VERIFIER(), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -16), /* *(fp - 16) = r1 */ BPF_LD_MAP_FD(BPF_REG_9, mapfd), BPF_MAP_GET(0, BPF_REG_6), /* r6 = op */ BPF_MAP_GET(1, BPF_REG_7), /* r7 = address */ BPF_MAP_GET(2, BPF_REG_8), /* r8 = value */ /* store map slot address in r2 */ BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), /* r2 = r0 */ BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 for exit(0) */ BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 2), /* if (op == 0) */ /* get fp */ BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, 0), BPF_EXIT_INSN(), BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 1, 3), /* else if (op == 1) */ /* get skbuff */ BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_10, -16), BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0), BPF_EXIT_INSN(), BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 2, 3), /* else if (op == 2) */ /* read */ BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_7, 0), BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0), BPF_EXIT_INSN(), /* else */ /* write */ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_8, 0), BPF_EXIT_INSN(), }; return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog), "GPL", 0); } void info(const char *fmt, ...) { va_list args; va_start(args, fmt); fprintf(stdout, "[.] "); vfprintf(stdout, fmt, args); va_end(args); }
static void test_obj_name(void) { struct { const char *name; int success; int expected_errno; } tests[] = { { "", 1, 0 }, { "_123456789ABCDE", 1, 0 }, { "_123456789ABCDEF", 0, EINVAL }, { "_123456789ABCD\n", 0, EINVAL }, }; struct bpf_insn prog[] = { BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), BPF_EXIT_INSN(), }; __u32 duration = 0; int i; for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { size_t name_len = strlen(tests[i].name) + 1; union bpf_attr attr; size_t ncopy; int fd; /* test different attr.prog_name during BPF_PROG_LOAD */ ncopy = name_len < sizeof(attr.prog_name) ? name_len : sizeof(attr.prog_name); bzero(&attr, sizeof(attr)); attr.prog_type = BPF_PROG_TYPE_SCHED_CLS; attr.insn_cnt = 2; attr.insns = ptr_to_u64(prog); attr.license = ptr_to_u64(""); memcpy(attr.prog_name, tests[i].name, ncopy); fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); CHECK((tests[i].success && fd < 0) || (!tests[i].success && fd != -1) || (!tests[i].success && errno != tests[i].expected_errno), "check-bpf-prog-name", "fd %d(%d) errno %d(%d)\n", fd, tests[i].success, errno, tests[i].expected_errno); if (fd != -1) close(fd); /* test different attr.map_name during BPF_MAP_CREATE */ ncopy = name_len < sizeof(attr.map_name) ? name_len : sizeof(attr.map_name); bzero(&attr, sizeof(attr)); attr.map_type = BPF_MAP_TYPE_ARRAY; attr.key_size = 4; attr.value_size = 4; attr.max_entries = 1; attr.map_flags = 0; memcpy(attr.map_name, tests[i].name, ncopy); fd = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr)); CHECK((tests[i].success && fd < 0) || (!tests[i].success && fd != -1) || (!tests[i].success && errno != tests[i].expected_errno), "check-bpf-map-name", "fd %d(%d) errno %d(%d)\n", fd, tests[i].success, errno, tests[i].expected_errno); if (fd != -1) close(fd); } }
int main(int argc, char** argv) { int fd,bpf_fd; struct perf_event_attr pe1; int errors=0; unsigned long long text_begin,symbol; union bpf_attr battr; int result; char test_string[]="Testing PERF_EVENT_IOC_SET_BPF ioctl..."; quiet=test_quiet(); if (!quiet) { printf("Testing PERF_EVENT_IOC_SET_BPF ioctl.\n"); } /*******************************************/ /* Creating a kprobe tracepoint event */ /*******************************************/ if (!quiet) { printf("Creating a kprobe tracepoint event\n"); } FILE *fff; int kprobe_id; char filename[BUFSIZ]; char tracefs_location[BUFSIZ]; char *find_result; find_result=find_tracefs_location(tracefs_location,quiet); if (find_result==NULL) { if (!quiet) { fprintf(stderr,"Error finding tracefs location!\n"); } test_skip(test_string); } sprintf(filename,"%s/kprobe_events",tracefs_location); fff=fopen(filename, "w"); if (fff==NULL) { printf("Cannot open %s!\n",filename); printf("You may want to: mount -t tracefs nodev /sys/kernel/tracing\n"); test_fail(test_string); } text_begin=lookup_symbol("_text"); symbol=lookup_symbol("handle_mm_fault"); if ((text_begin==0) || (symbol==0)) { fprintf(stderr,"Error finding symbol _text, handle_mm_fault\n"); test_fail(test_string); } /* perf probe -a VMW=handle_mm_fault */ fprintf(fff,"p:probe/VMW _text+%lld",symbol-text_begin); fclose(fff); sprintf(filename,"%s/events/probe/VMW/id",tracefs_location); fff=fopen(filename, "r"); if (fff==NULL) { printf("Cannot open %s!\n",filename); test_fail(test_string); } fscanf(fff,"%d",&kprobe_id); fclose(fff); memset(&pe1,0,sizeof(struct perf_event_attr)); pe1.type=PERF_TYPE_TRACEPOINT; pe1.size=sizeof(struct perf_event_attr); pe1.config=kprobe_id; pe1.disabled=1; pe1.exclude_kernel=0; pe1.exclude_hv=0; arch_adjust_domain(&pe1,quiet); /* Create group leader */ fd=perf_event_open(&pe1,0,-1,-1,0); if (fd<0) { if (!quiet) { fprintf(stderr,"Unexpected error %s\n",strerror(errno)); } printf("Cannot open kprobe id %d\n",kprobe_id); test_fail(test_string); } struct bpf_insn instructions[] = { BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 */ BPF_EXIT_INSN(), /* return r0 */ }; unsigned char license[]="GPL"; #define LOG_BUF_SIZE 65536 static char bpf_log_buf[LOG_BUF_SIZE]; /* Kernel will EINVAL if unused bits aren't zero */ memset(&battr,0,sizeof(battr)); /* Version has to match currently running kernel */ struct utsname version; int major, minor, subminor, version_code; uname(&version); printf("We are running release %s\n",version.release); sscanf(version.release,"%d.%d.%d",&major,&minor,&subminor); version_code = (major<<16) | (minor<<8) | subminor; printf("Using LINUX_VERSION_CODE: %d\n", version_code); battr.prog_type = BPF_PROG_TYPE_KPROBE; // battr.insn_cnt = sizeof(instructions); battr.insn_cnt= sizeof(instructions) / sizeof(struct bpf_insn); battr.insns = (uint64_t) (unsigned long) instructions; battr.license = (uint64_t) (unsigned long) license; battr.log_buf = (uint64_t) (unsigned long) bpf_log_buf; battr.log_size = LOG_BUF_SIZE; battr.log_level = 1; battr.kern_version = version_code; bpf_log_buf[0] = 0; bpf_fd = sys_bpf(BPF_PROG_LOAD, &battr, sizeof(battr)); if (bpf_fd < 0) { printf("bpf: load: failed to load program, %s\n" "-- BEGIN DUMP LOG ---\n%s\n-- END LOG --\n", strerror(errno), bpf_log_buf); return bpf_fd; } result=ioctl(fd, PERF_EVENT_IOC_SET_BPF, bpf_fd); if (result<0) { if (!quiet) printf("Unexpected %d %s\n",result,strerror(errno)); errors++; } /* start */ ioctl(fd, PERF_EVENT_IOC_ENABLE,0); /* million */ result=instructions_million(); /* stop */ ioctl(fd, PERF_EVENT_IOC_DISABLE,0); close(fd); fff=fopen(filename,"a"); if (fff==NULL) { fprintf(stderr,"Couldn't open %s for closing\n",filename); test_fail(test_string); } fprintf(fff,"-:probe/VMW\n"); fclose(fff); if (errors) { test_fail(test_string); } test_pass(test_string); return 0; }
int main(int argc, char** argv) { int fd,bpf_fd,test_fd; struct perf_event_attr pe1; int errors=0; int i; union bpf_attr battr; int result; char test_string[]="Testing eBPF load..."; quiet=test_quiet(); if (!quiet) { printf("Testing eBPF load.\n"); } /*******************************************/ /* Creating a kprobe tracepoint event */ /*******************************************/ if (!quiet) { printf("Creating a kprobe tracepoint event\n"); } FILE *fff; int kprobe_id; char filename[BUFSIZ]; char tracefs_location[BUFSIZ]; char *find_result; find_result=find_tracefs_location(tracefs_location,quiet); if (find_result==NULL) { if (!quiet) { fprintf(stderr,"Error finding tracefs location!\n"); fprintf(stderr,"Try sudo mount -t tracefs tracefs /sys/kernel/tracing/\n"); } test_skip(test_string); } sprintf(filename,"%s/kprobe_events",tracefs_location); fff=fopen(filename, "w+"); if (fff==NULL) { printf("Cannot open %s!\n",filename); test_fail(test_string); } /* where do these values come from? */ fprintf(fff,"p:perf_bpf_probe/func_write _text+2159216"); fclose(fff); sprintf(filename,"%s/events/perf_bpf_probe/func_write/id",tracefs_location); fff=fopen(filename, "r"); if (fff==NULL) { printf("Cannot open %s!\n",filename); test_fail(test_string); } fscanf(fff,"%d",&kprobe_id); fclose(fff); /* Setup BPF */ struct bpf_insn instructions[] = { BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 */ BPF_EXIT_INSN(), /* return r0 */ }; char bpf_prog[BPF_PROG_SIZE]; int bpf_prog_fd,bpf_prog_size; bpf_prog_fd=open("test_bpf_output.o",O_RDONLY); if (bpf_prog_fd<0) { fprintf(stderr,"Error opening bpf_output.o"); } bpf_prog_size=read(bpf_prog_fd,bpf_prog,BPF_PROG_SIZE); close(bpf_prog_fd); unsigned char license[]="GPL"; static char bpf_log_buf[LOG_BUF_SIZE]; /* Kernel will EINVAL if unused bits aren't zero */ memset(&battr,0,sizeof(battr)); /* Version has to match currently running kernel */ struct utsname version; int major, minor, subminor, version_code; uname(&version); printf("We are running release %s\n",version.release); sscanf(version.release,"%d.%d.%d",&major,&minor,&subminor); version_code = (major<<16) | (minor<<8) | subminor; printf("Using LINUX_VERSION_CODE: %d\n", version_code); battr.prog_type = BPF_PROG_TYPE_KPROBE; #if 0 // battr.insn_cnt = sizeof(instructions); battr.insn_cnt= sizeof(instructions) / sizeof(struct bpf_insn); battr.insns = (uint64_t) (unsigned long) instructions; #endif battr.insn_cnt= bpf_prog_size / sizeof(struct bpf_insn); battr.insns = (uint64_t) (unsigned long) bpf_prog; battr.license = (uint64_t) (unsigned long) license; battr.log_buf = (uint64_t) (unsigned long) bpf_log_buf; battr.log_size = LOG_BUF_SIZE; battr.log_level = 1; battr.kern_version = version_code; bpf_log_buf[0] = 0; bpf_fd = sys_bpf(BPF_PROG_LOAD, &battr, sizeof(battr)); if (bpf_fd < 0) { printf("bpf: load: failed to load program, %s\n" "-- BEGIN DUMP LOG ---\n%s\n-- END LOG --\n", strerror(errno), bpf_log_buf); return bpf_fd; } memset(&pe1,0,sizeof(struct perf_event_attr)); pe1.type=PERF_TYPE_TRACEPOINT; pe1.size=sizeof(struct perf_event_attr); pe1.config=kprobe_id; pe1.disabled=1; pe1.exclude_kernel=0; pe1.exclude_hv=0; arch_adjust_domain(&pe1,quiet); /* Create group leader */ fd=perf_event_open(&pe1,0,-1,-1,0); if (fd<0) { if (!quiet) { fprintf(stderr,"Unexpected error %s\n",strerror(errno)); } printf("Cannot open kprobe id %d\n",kprobe_id); test_fail(test_string); } result=ioctl(fd, PERF_EVENT_IOC_SET_BPF, bpf_fd); if (result<0) { if (!quiet) printf("Unexpected %d %s\n",result,strerror(errno)); errors++; } test_fd=open("/dev/null",O_WRONLY); if (test_fd<0) { fprintf(stderr,"Error opening /dev/null\n"); } /* start */ ioctl(fd, PERF_EVENT_IOC_ENABLE,0); for(i=0;i<10;i++) { write(test_fd,"Test!\n",7); } /* stop */ ioctl(fd, PERF_EVENT_IOC_DISABLE,0); close(test_fd); long long presult[32]; read(fd,presult,8); close(fd); if (errors) { test_fail(test_string); } test_pass(test_string); return 0; }