mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
Add more test cases for invalid instructions and add comments
about bpf_validate(9) issues.
This commit is contained in:
parent
95f20c6568
commit
bf2a220894
7 changed files with 232 additions and 9 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# $FreeBSD$
|
||||
|
||||
TEST_CASES= test0001 test0002 test0003 test0004 \
|
||||
TEST_CASES?= test0001 test0002 test0003 test0004 \
|
||||
test0005 test0006 test0007 test0008 \
|
||||
test0009 test0010 test0011 test0012 \
|
||||
test0013 test0014 test0015 test0016 \
|
||||
|
|
@ -18,9 +18,8 @@ TEST_CASES= test0001 test0002 test0003 test0004 \
|
|||
test0061 test0062 test0063 test0064 \
|
||||
test0065 test0066 test0067 test0068 \
|
||||
test0069 test0070 test0071 test0072 \
|
||||
test0073 test0074
|
||||
|
||||
WARNS?= 6
|
||||
test0073 test0074 test0075 test0076 \
|
||||
test0077 test0078
|
||||
|
||||
SYSDIR?= ${.CURDIR}/../../../../sys
|
||||
|
||||
|
|
@ -35,15 +34,17 @@ CFLAGS+= -DLOG_LEVEL="${LOG_LEVEL}"
|
|||
.endif
|
||||
|
||||
.if defined(BPF_VALIDATE)
|
||||
CFLAGS+= -DBPF_VALIDATE
|
||||
CFLAGS+= -DBPF_VALIDATE=${BPF_VALIDATE}
|
||||
.endif
|
||||
|
||||
.if (${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386") && defined(BPF_JIT)
|
||||
SRCS+= ${SYSDIR}/net/bpf_jitter.c \
|
||||
${SYSDIR}/${MACHINE_ARCH}/${MACHINE_ARCH}/bpf_jit_machdep.c
|
||||
CFLAGS+= -DBPF_JIT_COMPILER
|
||||
WARNS?= 6
|
||||
.else
|
||||
SRCS+= ${SYSDIR}/net/bpf_filter.c
|
||||
WARNS?= 2
|
||||
.endif
|
||||
|
||||
.for TEST in ${TEST_CASES}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@ bpf_compile_and_filter(void)
|
|||
return (ret);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BPF_VALIDATE
|
||||
|
|
@ -122,6 +126,61 @@ bpf_validate(const struct bpf_insn *f, int len)
|
|||
* the code block.
|
||||
*/
|
||||
p = &f[i];
|
||||
#if BPF_VALIDATE > 1
|
||||
/*
|
||||
* XXX JK: Illegal instructions must be checked here.
|
||||
*/
|
||||
switch (p->code) {
|
||||
default:
|
||||
return (0);
|
||||
case BPF_RET|BPF_K:
|
||||
case BPF_RET|BPF_A:
|
||||
case BPF_LD|BPF_W|BPF_ABS:
|
||||
case BPF_LD|BPF_H|BPF_ABS:
|
||||
case BPF_LD|BPF_B|BPF_ABS:
|
||||
case BPF_LD|BPF_W|BPF_LEN:
|
||||
case BPF_LDX|BPF_W|BPF_LEN:
|
||||
case BPF_LD|BPF_W|BPF_IND:
|
||||
case BPF_LD|BPF_H|BPF_IND:
|
||||
case BPF_LD|BPF_B|BPF_IND:
|
||||
case BPF_LDX|BPF_MSH|BPF_B:
|
||||
case BPF_LD|BPF_IMM:
|
||||
case BPF_LDX|BPF_IMM:
|
||||
case BPF_LD|BPF_MEM:
|
||||
case BPF_LDX|BPF_MEM:
|
||||
case BPF_ST:
|
||||
case BPF_STX:
|
||||
case BPF_JMP|BPF_JA:
|
||||
case BPF_JMP|BPF_JGT|BPF_K:
|
||||
case BPF_JMP|BPF_JGE|BPF_K:
|
||||
case BPF_JMP|BPF_JEQ|BPF_K:
|
||||
case BPF_JMP|BPF_JSET|BPF_K:
|
||||
case BPF_JMP|BPF_JGT|BPF_X:
|
||||
case BPF_JMP|BPF_JGE|BPF_X:
|
||||
case BPF_JMP|BPF_JEQ|BPF_X:
|
||||
case BPF_JMP|BPF_JSET|BPF_X:
|
||||
case BPF_ALU|BPF_ADD|BPF_X:
|
||||
case BPF_ALU|BPF_SUB|BPF_X:
|
||||
case BPF_ALU|BPF_MUL|BPF_X:
|
||||
case BPF_ALU|BPF_DIV|BPF_X:
|
||||
case BPF_ALU|BPF_AND|BPF_X:
|
||||
case BPF_ALU|BPF_OR|BPF_X:
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
case BPF_ALU|BPF_RSH|BPF_X:
|
||||
case BPF_ALU|BPF_ADD|BPF_K:
|
||||
case BPF_ALU|BPF_SUB|BPF_K:
|
||||
case BPF_ALU|BPF_MUL|BPF_K:
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
case BPF_ALU|BPF_AND|BPF_K:
|
||||
case BPF_ALU|BPF_OR|BPF_K:
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
case BPF_ALU|BPF_RSH|BPF_K:
|
||||
case BPF_ALU|BPF_NEG:
|
||||
case BPF_MISC|BPF_TAX:
|
||||
case BPF_MISC|BPF_TXA:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (BPF_CLASS(p->code) == BPF_JMP) {
|
||||
register int from = i + 1;
|
||||
|
||||
|
|
@ -137,10 +196,20 @@ bpf_validate(const struct bpf_insn *f, int len)
|
|||
* Check that memory operations use valid addresses.
|
||||
*/
|
||||
if ((BPF_CLASS(p->code) == BPF_ST ||
|
||||
(BPF_CLASS(p->code) == BPF_LD &&
|
||||
(p->code & 0xe0) == BPF_MEM)) &&
|
||||
(BPF_CLASS(p->code) == BPF_LD &&
|
||||
(p->code & 0xe0) == BPF_MEM)) &&
|
||||
p->k >= BPF_MEMWORDS)
|
||||
return (0);
|
||||
#if BPF_VALIDATE > 1
|
||||
/*
|
||||
* XXX JK: BPF_STX and BPF_LDX|BPF_MEM must be checked.
|
||||
*/
|
||||
if ((BPF_CLASS(p->code) == BPF_STX ||
|
||||
(BPF_CLASS(p->code) == BPF_LDX &&
|
||||
(p->code & 0xe0) == BPF_MEM)) &&
|
||||
p->k >= BPF_MEMWORDS)
|
||||
return (0);
|
||||
#endif
|
||||
/*
|
||||
* Check for constant division by 0.
|
||||
*/
|
||||
|
|
@ -171,16 +240,22 @@ main(void)
|
|||
valid = bpf_validate(pc, nins);
|
||||
if (valid != 0 && invalid != 0) {
|
||||
if (verbose > 1)
|
||||
printf("Validated invalid instructions:\t");
|
||||
printf("Validated invalid instruction(s):\t");
|
||||
if (verbose > 0)
|
||||
printf("FAILED\n");
|
||||
return (FAILED);
|
||||
} else if (valid == 0 && invalid == 0) {
|
||||
if (verbose > 1)
|
||||
printf("Invalidated valid instructions:\t");
|
||||
printf("Invalidated valid instruction(s):\t");
|
||||
if (verbose > 0)
|
||||
printf("FAILED\n");
|
||||
return (FAILED);
|
||||
} else if (invalid != 0) {
|
||||
if (verbose > 1)
|
||||
printf("Expected and invalidated:\t");
|
||||
if (verbose > 0)
|
||||
printf("PASSED\n");
|
||||
return (PASSED);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
/* BPF program */
|
||||
struct bpf_insn pc[] = {
|
||||
BPF_STMT(0xdead, 0),
|
||||
BPF_STMT(BPF_RET+BPF_A, 0),
|
||||
};
|
||||
|
||||
/* Packet */
|
||||
|
|
|
|||
36
tools/regression/bpf/bpf_filter/tests/test0075.h
Normal file
36
tools/regression/bpf/bpf_filter/tests/test0075.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*-
|
||||
* Test 0075: Check boundary conditions (BPF_LD|BPF_MEM)
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* BPF program */
|
||||
struct bpf_insn pc[] = {
|
||||
BPF_STMT(BPF_LD|BPF_IMM, 0xdeadc0de),
|
||||
BPF_STMT(BPF_LD|BPF_MEM, 0xffffffff),
|
||||
BPF_STMT(BPF_RET+BPF_A, 0),
|
||||
};
|
||||
|
||||
/* Packet */
|
||||
u_char pkt[] = {
|
||||
0x00,
|
||||
};
|
||||
|
||||
/* Packet length seen on wire */
|
||||
u_int wirelen = sizeof(pkt);
|
||||
|
||||
/* Packet length passed on buffer */
|
||||
u_int buflen = sizeof(pkt);
|
||||
|
||||
/* Invalid instruction */
|
||||
int invalid = 1;
|
||||
|
||||
/* Expected return value */
|
||||
u_int expect = 0xdeadc0de;
|
||||
|
||||
/* Expeced signal */
|
||||
#ifdef BPF_JIT_COMPILER
|
||||
int expect_signal = SIGSEGV;
|
||||
#else
|
||||
int expect_signal = SIGBUS;
|
||||
#endif
|
||||
37
tools/regression/bpf/bpf_filter/tests/test0076.h
Normal file
37
tools/regression/bpf/bpf_filter/tests/test0076.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*-
|
||||
* Test 0076: Check boundary conditions (BPF_LDX|BPF_MEM)
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* BPF program */
|
||||
struct bpf_insn pc[] = {
|
||||
BPF_STMT(BPF_LD|BPF_IMM, 0xdeadc0de),
|
||||
BPF_STMT(BPF_LDX|BPF_MEM, 0xffffffff),
|
||||
BPF_STMT(BPF_MISC|BPF_TXA, 0),
|
||||
BPF_STMT(BPF_RET+BPF_A, 0),
|
||||
};
|
||||
|
||||
/* Packet */
|
||||
u_char pkt[] = {
|
||||
0x00,
|
||||
};
|
||||
|
||||
/* Packet length seen on wire */
|
||||
u_int wirelen = sizeof(pkt);
|
||||
|
||||
/* Packet length passed on buffer */
|
||||
u_int buflen = sizeof(pkt);
|
||||
|
||||
/* Invalid instruction */
|
||||
int invalid = 1;
|
||||
|
||||
/* Expected return value */
|
||||
u_int expect = 0xdeadc0de;
|
||||
|
||||
/* Expeced signal */
|
||||
#ifdef BPF_JIT_COMPILER
|
||||
int expect_signal = SIGSEGV;
|
||||
#else
|
||||
int expect_signal = SIGBUS;
|
||||
#endif
|
||||
36
tools/regression/bpf/bpf_filter/tests/test0077.h
Normal file
36
tools/regression/bpf/bpf_filter/tests/test0077.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*-
|
||||
* Test 0077: Check boundary conditions (BPF_ST)
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* BPF program */
|
||||
struct bpf_insn pc[] = {
|
||||
BPF_STMT(BPF_LD|BPF_IMM, 0xdeadc0de),
|
||||
BPF_STMT(BPF_ST, 0xffffffff),
|
||||
BPF_STMT(BPF_RET+BPF_A, 0),
|
||||
};
|
||||
|
||||
/* Packet */
|
||||
u_char pkt[] = {
|
||||
0x00,
|
||||
};
|
||||
|
||||
/* Packet length seen on wire */
|
||||
u_int wirelen = sizeof(pkt);
|
||||
|
||||
/* Packet length passed on buffer */
|
||||
u_int buflen = sizeof(pkt);
|
||||
|
||||
/* Invalid instruction */
|
||||
int invalid = 1;
|
||||
|
||||
/* Expected return value */
|
||||
u_int expect = 0xdeadc0de;
|
||||
|
||||
/* Expeced signal */
|
||||
#ifdef BPF_JIT_COMPILER
|
||||
int expect_signal = SIGSEGV;
|
||||
#else
|
||||
int expect_signal = SIGBUS;
|
||||
#endif
|
||||
37
tools/regression/bpf/bpf_filter/tests/test0078.h
Normal file
37
tools/regression/bpf/bpf_filter/tests/test0078.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*-
|
||||
* Test 0078: Check boundary conditions (BPF_STX)
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* BPF program */
|
||||
struct bpf_insn pc[] = {
|
||||
BPF_STMT(BPF_LD|BPF_IMM, 0xdeadc0de),
|
||||
BPF_STMT(BPF_STX, 0xffffffff),
|
||||
BPF_STMT(BPF_MISC|BPF_TXA, 0),
|
||||
BPF_STMT(BPF_RET+BPF_A, 0),
|
||||
};
|
||||
|
||||
/* Packet */
|
||||
u_char pkt[] = {
|
||||
0x00,
|
||||
};
|
||||
|
||||
/* Packet length seen on wire */
|
||||
u_int wirelen = sizeof(pkt);
|
||||
|
||||
/* Packet length passed on buffer */
|
||||
u_int buflen = sizeof(pkt);
|
||||
|
||||
/* Invalid instruction */
|
||||
int invalid = 1;
|
||||
|
||||
/* Expected return value */
|
||||
u_int expect = 0xdeadc0de;
|
||||
|
||||
/* Expeced signal */
|
||||
#ifdef BPF_JIT_COMPILER
|
||||
int expect_signal = SIGSEGV;
|
||||
#else
|
||||
int expect_signal = SIGBUS;
|
||||
#endif
|
||||
Loading…
Reference in a new issue