Add more test cases for invalid instructions and add comments

about bpf_validate(9) issues.
This commit is contained in:
Jung-uk Kim 2008-08-26 19:24:58 +00:00
parent 95f20c6568
commit bf2a220894
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=182219
7 changed files with 232 additions and 9 deletions

View File

@ -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}

View File

@ -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

View File

@ -7,6 +7,7 @@
/* BPF program */
struct bpf_insn pc[] = {
BPF_STMT(0xdead, 0),
BPF_STMT(BPF_RET+BPF_A, 0),
};
/* Packet */

View 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

View 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

View 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

View 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