snorez / ebpf-fuzzer Goto Github PK
View Code? Open in Web Editor NEWfuzz the linux kernel bpf verifier
fuzz the linux kernel bpf verifier
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)
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;
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.