Giter VIP home page Giter VIP logo

ebpf-fuzzer's People

Contributors

snorez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ebpf-fuzzer's Issues

total: 0, valid: 0(-nan%), crash: 0(reason: 0)

This project is awesome, and I have mutated the example successfully (outfile:/tmp/test_sample.c), but I don't now why the output like these:

[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)

[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0) AND load_prog() err

Thanks to your great idea and project !

When I run the project with the correct kernel CONFIG (including CONFIG_BPF_SYSCALL=y , CONFIG_BPF_JIT=y),

but I still got the ouput:

root@ubuntu:~/ebpf-fuzzer# ./ebpf_fuzzer /root/ebpf-fuzzer/config 0
qemu_fuzzlib_env_setup ...done
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)
[ebpf_fuzzer]: total: 0, valid: 0(-nan%), crash: 0(reason: 0)

After that, I tried to run:

./ebpf_fuzzer /root/ebpf-fuzzer/config 1

And then got a test file in /tmp/test_sample.c

So I compile this file in the host and it succeed.

Finally I run the file, but I got ๏ผš

root@ubuntu:~/ebpf-fuzzer# ./ebpf_fuzzer ./config 1
root@ubuntu:~/ebpf-fuzzer# gcc /tmp/test_sample.c -o ./test_sample

root@ubuntu:~/ebpf-fuzzer# ./test_sample 
update_storage_map done.
repro failed

Then I check the test_sample.c and open some fprintf() for error, and re-compile test_sample.c , which finally got:

root@ubuntu:~/ebpf-fuzzer# ./test_sample 
update_storage_map done.
load_prog() err
repro failed

It seems that the struct bpf_insn __insns[] load failed which made the fuzzer in a abnormal state?

The test_sample.c is :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/bpf.h>
#include <linux/bpf_common.h>
#include <sys/prctl.h>

enum qemu_fuzzlib_inst_res {
	QEMU_FUZZLIB_INST_INVALID = -1,
	QEMU_FUZZLIB_INST_NOT_TESTED = 0,
	QEMU_FUZZLIB_INST_VALID,
	QEMU_FUZZLIB_INST_BOOM,
};

typedef __s8	s8;
typedef __s16	s16;
typedef __s32	s32;
typedef __s64	s64;
typedef __u8	u8;
typedef __u16	u16;
typedef __u32	u32;
typedef __u64	u64;

struct xmsg {
	unsigned long		special_value;
	unsigned long		insn_cnt;
	struct bpf_insn		insns[BPF_MAXINSNS];
};

#ifndef BPF_JMP32
#define	BPF_JMP32	0x06
#endif

/* ArgX, context and stack frame pointer register positions. Note,
 * Arg1, Arg2, Arg3, etc are used as argument mappings of function
 * calls in BPF_CALL instruction.
 */
#define BPF_REG_ARG1	BPF_REG_1
#define BPF_REG_ARG2	BPF_REG_2
#define BPF_REG_ARG3	BPF_REG_3
#define BPF_REG_ARG4	BPF_REG_4
#define BPF_REG_ARG5	BPF_REG_5
#define BPF_REG_CTX	BPF_REG_6
#define BPF_REG_FP	BPF_REG_10

/* Additional register mappings for converted user programs. */
#define BPF_REG_A	BPF_REG_0
#define BPF_REG_X	BPF_REG_7
#define BPF_REG_TMP	BPF_REG_2	/* scratch reg */
#define BPF_REG_D	BPF_REG_8	/* data, callee-saved */
#define BPF_REG_H	BPF_REG_9	/* hlen, callee-saved */

/* Kernel hidden auxiliary/helper register. */
#define BPF_REG_AX		MAX_BPF_REG
#define MAX_BPF_EXT_REG		(MAX_BPF_REG + 1)
#define MAX_BPF_JIT_REG		MAX_BPF_EXT_REG

/* unused opcode to mark special call to bpf_tail_call() helper */
#define BPF_TAIL_CALL	0xf0

/* unused opcode to mark call to interpreter with arguments */
#define BPF_CALL_ARGS	0xe0

/* As per nm, we expose JITed images as text (code) section for
 * kallsyms. That way, tools like perf can find it to match
 * addresses.
 */
#define BPF_SYM_ELF_TYPE	't'

/* BPF program can access up to 512 bytes of stack space. */
#define MAX_BPF_STACK	512

/* Helper macros for filter block array initializers. */

/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */

#define BPF_ALU64_REG(OP, DST, SRC)				\
	((struct bpf_insn) {					\
		.code  = BPF_ALU64 | BPF_OP(OP) | BPF_X,	\
		.dst_reg = DST,					\
		.src_reg = SRC,					\
		.off   = 0,					\
		.imm   = 0 })

#define BPF_ALU32_REG(OP, DST, SRC)				\
	((struct bpf_insn) {					\
		.code  = BPF_ALU | BPF_OP(OP) | BPF_X,		\
		.dst_reg = DST,					\
		.src_reg = SRC,					\
		.off   = 0,					\
		.imm   = 0 })

/* ALU ops on immediates, bpf_add|sub|...: dst_reg += imm32 */

#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_ALU32_IMM(OP, DST, IMM)				\
	((struct bpf_insn) {					\
		.code  = BPF_ALU | BPF_OP(OP) | BPF_K,		\
		.dst_reg = DST,					\
		.src_reg = 0,					\
		.off   = 0,					\
		.imm   = IMM })

/* Endianess conversion, cpu_to_{l,b}e(), {l,b}e_to_cpu() */

#define BPF_ENDIAN(TYPE, DST, LEN)				\
	((struct bpf_insn) {					\
		.code  = BPF_ALU | BPF_END | BPF_SRC(TYPE),	\
		.dst_reg = DST,					\
		.src_reg = 0,					\
		.off   = 0,					\
		.imm   = LEN })

/* Short form of mov, dst_reg = src_reg */

#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 })

/* Short form of mov, dst_reg = imm32 */

#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 })

/* Special form of mov32, used for doing explicit zero extension on dst. */
#define BPF_ZEXT_REG(DST)					\
	((struct bpf_insn) {					\
		.code  = BPF_ALU | BPF_MOV | BPF_X,		\
		.dst_reg = DST,					\
		.src_reg = DST,					\
		.off   = 0,					\
		.imm   = 1 })

/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */
#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, /* zero is reserved opcode */	\
		.dst_reg = 0,					\
		.src_reg = 0,					\
		.off   = 0,					\
		.imm   = ((__u64) (IMM)) >> 32 })

/* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */
#define BPF_LD_MAP_FD(DST, MAP_FD)				\
	BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)

/* Short form of mov based on type, BPF_X: dst_reg = src_reg, BPF_K: dst_reg = imm32 */

#define BPF_MOV64_RAW(TYPE, DST, SRC, IMM)			\
	((struct bpf_insn) {					\
		.code  = BPF_ALU64 | BPF_MOV | BPF_SRC(TYPE),	\
		.dst_reg = DST,					\
		.src_reg = SRC,					\
		.off   = 0,					\
		.imm   = IMM })

#define BPF_MOV32_RAW(TYPE, DST, SRC, IMM)			\
	((struct bpf_insn) {					\
		.code  = BPF_ALU | BPF_MOV | BPF_SRC(TYPE),	\
		.dst_reg = DST,					\
		.src_reg = SRC,					\
		.off   = 0,					\
		.imm   = IMM })

/* Direct packet access, R0 = *(uint *) (skb->data + imm32) */

#define BPF_LD_ABS(SIZE, IMM)					\
	((struct bpf_insn) {					\
		.code  = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS,	\
		.dst_reg = 0,					\
		.src_reg = 0,					\
		.off   = 0,					\
		.imm   = IMM })

/* Indirect packet access, R0 = *(uint *) (skb->data + src_reg + imm32) */

#define BPF_LD_IND(SIZE, SRC, IMM)				\
	((struct bpf_insn) {					\
		.code  = BPF_LD | BPF_SIZE(SIZE) | BPF_IND,	\
		.dst_reg = 0,					\
		.src_reg = SRC,					\
		.off   = 0,					\
		.imm   = IMM })

/* Memory load, dst_reg = *(uint *) (src_reg + off16) */

#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 })

/* Memory store, *(uint *) (dst_reg + off16) = src_reg */

#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 })

/* Atomic memory add, *(uint *)(dst_reg + off16) += src_reg */

#define BPF_STX_XADD(SIZE, DST, SRC, OFF)			\
	((struct bpf_insn) {					\
		.code  = BPF_STX | BPF_SIZE(SIZE) | BPF_XADD,	\
		.dst_reg = DST,					\
		.src_reg = SRC,					\
		.off   = OFF,					\
		.imm   = 0 })

/* Memory store, *(uint *) (dst_reg + off16) = imm32 */

#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 })

/* Conditional jumps against registers, if (dst_reg 'op' src_reg) goto pc + off16 */

#define BPF_JMP_REG(OP, DST, SRC, OFF)				\
	((struct bpf_insn) {					\
		.code  = BPF_JMP | BPF_OP(OP) | BPF_X,		\
		.dst_reg = DST,					\
		.src_reg = SRC,					\
		.off   = OFF,					\
		.imm   = 0 })

/* Conditional jumps against immediates, if (dst_reg 'op' imm32) goto pc + off16 */

#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 })

/* Like BPF_JMP_REG, but with 32-bit wide operands for comparison. */

#define BPF_JMP32_REG(OP, DST, SRC, OFF)			\
	((struct bpf_insn) {					\
		.code  = BPF_JMP32 | BPF_OP(OP) | BPF_X,	\
		.dst_reg = DST,					\
		.src_reg = SRC,					\
		.off   = OFF,					\
		.imm   = 0 })

/* Like BPF_JMP_IMM, but with 32-bit wide operands for comparison. */

#define BPF_JMP32_IMM(OP, DST, IMM, OFF)			\
	((struct bpf_insn) {					\
		.code  = BPF_JMP32 | BPF_OP(OP) | BPF_K,	\
		.dst_reg = DST,					\
		.src_reg = 0,					\
		.off   = OFF,					\
		.imm   = IMM })

/* Unconditional jumps, goto pc + off16 */

#define BPF_JMP_A(OFF)						\
	((struct bpf_insn) {					\
		.code  = BPF_JMP | BPF_JA,			\
		.dst_reg = 0,					\
		.src_reg = 0,					\
		.off   = OFF,					\
		.imm   = 0 })

/* Relative call */

#define BPF_CALL_REL(TGT)					\
	((struct bpf_insn) {					\
		.code  = BPF_JMP | BPF_CALL,			\
		.dst_reg = 0,					\
		.src_reg = BPF_PSEUDO_CALL,			\
		.off   = 0,					\
		.imm   = TGT })

#define	__bpf_call_base 0
#define BPF_EMIT_CALL(FUNC)					\
	((struct bpf_insn) {					\
		.code  = BPF_JMP | BPF_CALL,			\
		.dst_reg = 0,					\
		.src_reg = 0,					\
		.off   = 0,					\
		.imm   = ((FUNC) - __bpf_call_base) })

/* Raw code statement block */

#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM)			\
	((struct bpf_insn) {					\
		.code  = CODE,					\
		.dst_reg = DST,					\
		.src_reg = SRC,					\
		.off   = OFF,					\
		.imm   = IMM })

/* Program exit */

#define BPF_EXIT_INSN()						\
	((struct bpf_insn) {					\
		.code  = BPF_JMP | BPF_EXIT,			\
		.dst_reg = 0,					\
		.src_reg = 0,					\
		.off   = 0,					\
		.imm   = 0 })

#define	LISTENER_PORT		(1337)
#define	LISTENER_BACKLOG	(0x30)
#define	STORAGE_MAP_SIZE	(8192)
#define	FUZZ_MAP_SIZE		(8192)

#define	ARRAY_CNT(arr)	(sizeof(arr) / sizeof(arr[0]))

#define	CORRUPT_FD_CONST	10
#define	STORAGE_FD_CONST	11
#define	CORRUPT_REG		BPF_REG_9
#define	STORAGE_REG		BPF_REG_8
#define	SPECIAL_REG		BPF_REG_7
#define	INVALID_P_REG		BPF_REG_6
#define	LEAKED_V_REG		BPF_REG_5
#define	UMAX_REG		BPF_REG_4
#define	EXTRA0_REG		BPF_REG_3
#define	EXTRA1_REG		BPF_REG_2
#define	EXTRA2_REG		BPF_REG_1
#define	MAGIC_VAL1		0x4142434445464748
#define	MAGIC_VAL2		0x494a4b4c4d4e4f40

static int bpf(unsigned int cmd, union bpf_attr *attr, size_t size)
{
	return syscall(SYS_bpf, cmd, attr, size);
}

static int update_storage_map(int fd, unsigned long special_val)
{
	uint64_t key = 0;
	unsigned long buf[STORAGE_MAP_SIZE / sizeof(long)];
	buf[0] = special_val;
	for (int i = 1; i < (STORAGE_MAP_SIZE / sizeof(long)); i++) {
		buf[i] = MAGIC_VAL2;
	}
	union bpf_attr attr = {
		.map_fd = fd,
		.key = (uint64_t)&key,
		.value = (uint64_t)&buf,
	};

	return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}

static int update_corrupt_map(int fd)
{
	uint64_t key = 0;
	unsigned long buf[STORAGE_MAP_SIZE / sizeof(long)];
	for (int i = 0; i < (STORAGE_MAP_SIZE / sizeof(long)); i++) {
		buf[i] = MAGIC_VAL1;
	}
	union bpf_attr attr = {
		.map_fd = fd,
		.key = (uint64_t)&key,
		.value = (uint64_t)&buf,
	};

	return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}

static int init_maps(int *corrupt_map_fd, int *storage_map_fd)
{
	union bpf_attr corrupt_map = {
		.map_type = BPF_MAP_TYPE_ARRAY,
		.key_size = 4,
		.value_size = STORAGE_MAP_SIZE,
		.max_entries = 1,
	};
	strcpy(corrupt_map.map_name, "corrupt_map");
	*corrupt_map_fd = (int)bpf(BPF_MAP_CREATE, &corrupt_map,
				   sizeof(corrupt_map));
	if (*corrupt_map_fd < 0)
		return -1;

	if (update_corrupt_map(*corrupt_map_fd) < 0)
		return -1;

	union bpf_attr storage_map = {
		.map_type = BPF_MAP_TYPE_ARRAY,
		.key_size = 4,
		.value_size = STORAGE_MAP_SIZE,
		.max_entries = 1,
	};
	strcpy(corrupt_map.map_name, "storage_map");
	*storage_map_fd = (int)bpf(BPF_MAP_CREATE, &storage_map,
				   sizeof(storage_map));
	if (*storage_map_fd < 0)
		return -1;

	if (update_storage_map(*storage_map_fd, 0) < 0)
		return -1;

	return 0;
}

static int read_map(int fd, void *buf, size_t size)
{
	assert(size <= (STORAGE_MAP_SIZE));

	unsigned long lk[STORAGE_MAP_SIZE / sizeof(long)];
	memset(lk, 0, sizeof(lk));
	uint64_t key = 0;
	union bpf_attr lookup_map = {
		.map_fd = fd,
		.key = (uint64_t)&key,
		.value = (uint64_t)&lk,
	};

	int err = bpf(BPF_MAP_LOOKUP_ELEM, &lookup_map, sizeof(lookup_map));
	if (err < 0) {
		return -1;
	}

	memcpy(buf, lk, size);

	return 0;
}

static int setup_listener_sock(int port, int backlog)
{
	int sock_fd = socket(AF_INET,
				SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
				0);
	if (sock_fd < 0) {
		return sock_fd;
	}

	struct sockaddr_in servaddr;
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(port);
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

	int err = bind(sock_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));
	if (err < 0) {
		close(sock_fd);
		return err;
	}

	err = listen(sock_fd, backlog);
	if (err < 0) {
		close(sock_fd);
		return err;
	}

	return sock_fd;
}

static int setup_send_sock(void)
{
	return socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
}

#define	LOG_BUF_SIZE	65536
static char bpf_log_buf[LOG_BUF_SIZE];

static int load_prog(struct bpf_insn *insns, size_t insn_count)
{
	union bpf_attr prog = {};
	prog.license = (uint64_t)"GPL";
	strcpy(prog.prog_name, "ebpf_fuzzer");
	prog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
	prog.insn_cnt = insn_count;
	prog.insns = (uint64_t)insns;
	prog.log_buf = (uint64_t)bpf_log_buf;
	prog.log_size = LOG_BUF_SIZE;
	prog.log_level = 1;

	int prog_fd = bpf(BPF_PROG_LOAD, &prog, sizeof(prog));
	if (prog_fd < 0) {
		return -1;
	}

	return prog_fd;
}

static int exec_prog(int prog_fd, int *_err)
{
	int listener_sock = setup_listener_sock(LISTENER_PORT, LISTENER_BACKLOG);
	int send_sock = setup_send_sock();

	if ((listener_sock < 0) || (send_sock < 0)) {
		return -1;
	}

	if (setsockopt(listener_sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd,
			sizeof(prog_fd)) < 0) {
		return -1;
	}

	struct sockaddr_in servaddr;
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(LISTENER_PORT);
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

	int err;
	err = connect(send_sock, (struct sockaddr *)&servaddr, sizeof(servaddr));
	if (err < 0) {
		*_err = errno;
	}

	close(listener_sock);
	close(send_sock);
	return (err < 0) ? 1 : 0;
}

static int detect_oob(char *buf0, char *buf1, size_t size)
{
	char *b = &buf1[8];
	unsigned long *_b = (unsigned long *)buf1;
	for (int i = 0; i < 8; i++) {
		if ((b[i] > 0x4f) || (b[i] < 0x40)) {
			fprintf(stderr, "[1]: %lx\n", _b[1]);
			return 1;
		}
	}

	fprintf(stderr, "[2]: %lx\n", _b[2]);
	return 0;
}

static int repro_xmsg(int corrupt_map_fd, int storage_map_fd, struct xmsg *msg)
{
	int err = 0;
	char buf0[STORAGE_MAP_SIZE];
	char buf1[STORAGE_MAP_SIZE];

	err = update_storage_map(storage_map_fd, msg->special_value);
	if (err < 0) {
		fprintf(stderr, "update_storage_map err\n");
		return -1;
	}
	fprintf(stderr, "update_storage_map done.\n");

	err = read_map(storage_map_fd, buf0, STORAGE_MAP_SIZE);
	if (err < 0) {
		fprintf(stderr, "read_map err\n");
		return -1;
	}

	/* load and execute prog */
	int prog_fd = load_prog(msg->insns, msg->insn_cnt);
	if (prog_fd < 0) {
		fprintf(stderr, "load_prog() err\n");
		return -1;
	}
	fprintf(stderr, "%ld, %s.\n", strlen(bpf_log_buf), bpf_log_buf);

	int connect_err;
	err = exec_prog(prog_fd, &connect_err);
	if (err != 1) {
		/* prog not execute successfully */
		return 0;
	}
	fprintf(stderr, "exec_prog done.\n");

	/* read the map again, check the content */
	err = read_map(storage_map_fd, buf1, STORAGE_MAP_SIZE);
	if (err < 0) {
		fprintf(stderr, "read_map err\n");
		return -1;
	}

	if (detect_oob(buf0, buf1, STORAGE_MAP_SIZE)) {
		return 1;
	}

	return 0;
}

int main(int argc, char *argv[])
{
	struct xmsg msg;
	int corrupt_map_fd, storage_map_fd;
	int err;

	err = init_maps(&corrupt_map_fd, &storage_map_fd);
	if (err < 0) {
		fprintf(stderr, "init_maps err\n");
		return QEMU_FUZZLIB_INST_NOT_TESTED;
	}
	dup2(corrupt_map_fd, CORRUPT_FD_CONST);
	dup2(storage_map_fd, STORAGE_FD_CONST);
	close(corrupt_map_fd);
	close(storage_map_fd);
	corrupt_map_fd = CORRUPT_FD_CONST;
	storage_map_fd = STORAGE_FD_CONST;
	memset(&msg, 0, sizeof(msg));

	struct bpf_insn __insns[] = {
BPF_MOV64_IMM(BPF_REG_0, 0x0),
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 0xfffffffc),
BPF_LD_MAP_FD(BPF_REG_1, 0xa),
BPF_EMIT_CALL(0x1),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0x0, 1),
BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_9, BPF_REG_0),
BPF_MOV64_IMM(BPF_REG_0, 0x0),
BPF_MOV64_IMM(BPF_REG_0, 0x0),
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 0xfffffffc),
BPF_LD_MAP_FD(BPF_REG_1, 0xb),
BPF_EMIT_CALL(0x1),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0x0, 1),
BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
BPF_MOV64_IMM(BPF_REG_0, 0x0),
BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_8, 0),
BPF_LD_IMM64(BPF_REG_3, 0xd9f080a750714ba2),
BPF_ALU64_REG(BPF_DIV, BPF_REG_3, BPF_REG_7),
BPF_MOV64_IMM(BPF_REG_0, 0x0),
BPF_MOV64_IMM(BPF_REG_0, 0x0),
BPF_JMP32_REG(BPF_JA, BPF_REG_3, BPF_REG_7, 1),
BPF_EXIT_INSN(),
BPF_ALU64_REG(BPF_MUL, BPF_REG_3, BPF_REG_7),
BPF_ALU64_REG(BPF_MUL, BPF_REG_3, BPF_REG_7),
BPF_MOV32_REG(BPF_REG_3, BPF_REG_7),
BPF_MOV64_IMM(BPF_REG_0, 0x0),
BPF_MOV64_IMM(BPF_REG_0, 0x0),
BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_3, 1),
BPF_EXIT_INSN(),
BPF_ALU32_REG(BPF_RSH, BPF_REG_7, BPF_REG_3),
BPF_MOV64_IMM(BPF_REG_0, 0x0),
BPF_ALU32_IMM(BPF_MOD, BPF_REG_7, 0x74ea35c1),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_3, 0x6effe2c3, 1),
BPF_EXIT_INSN(),
BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 0xfb1a558c),
BPF_ALU32_IMM(BPF_DIV, BPF_REG_3, 0x18d2ddfb),
BPF_JMP_REG(BPF_JA, BPF_REG_3, BPF_REG_7, 1),
BPF_EXIT_INSN(),
BPF_ALU64_IMM(BPF_SUB, BPF_REG_7, 0xb9699376),
BPF_JMP_REG(BPF_JSGE, BPF_REG_3, BPF_REG_7, 1),
BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_6, BPF_REG_7),
BPF_ALU64_REG(BPF_SUB, BPF_REG_9, BPF_REG_6),
BPF_LDX_MEM(BPF_DW, BPF_REG_5, BPF_REG_9, 0),
BPF_STX_MEM(BPF_DW, BPF_REG_8, BPF_REG_5, 8),
BPF_MOV64_IMM(BPF_REG_0, 0x1),
BPF_EXIT_INSN(),
	};

	msg.special_value = 0x3695615b1b9746ab;
	msg.insn_cnt = ARRAY_CNT(__insns);
	memcpy(msg.insns, __insns, msg.insn_cnt * sizeof(struct bpf_insn));

	err = repro_xmsg(corrupt_map_fd, storage_map_fd, &msg);
	if (err == 1) {
		fprintf(stderr, "repro done\n");
		return QEMU_FUZZLIB_INST_BOOM;
	} else if (err == 0) {
		fprintf(stderr, "repro failed\n");
		return QEMU_FUZZLIB_INST_VALID;
	} else if (err == -1) {
		fprintf(stderr, "repro failed\n");
		return QEMU_FUZZLIB_INST_INVALID;
	}
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.