summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-07-25 11:41:35 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2012-07-25 12:49:35 +0200
commit4b6df760e3b19ec522b66cbbb5b280fec7c0405b (patch)
treec649ed518e701d0f8d4ef8deb56afe6c3b20e40a
parentd4dbc65c965cb4d94fb5967095e7aa1713ca57c6 (diff)
conntrack: fix autogenerated BPF code for IPv6 filtering
BPF code generated for IPv6 filtering was wrong. Assuming you want to allow all traffic except ::1, the filter that libnetfilter_conntrack generates for the IPv6 address part looks like: [...] (0032) code= BPF_LD|BPF_W|BPF_IND jt=00 jf=00 k=00000004 (0033) code= BPF_ALU|BPF_AND|BPF_K jt=00 jf=00 k=ffffffff (0034) code= BPF_JMP|BPF_JEQ|BPF_K jt=00 jf=0a k=00000000 (0035) code= BPF_LD|BPF_W|BPF_IND jt=00 jf=00 k=00000008 [0] (0036) code= BPF_ALU|BPF_AND|BPF_K jt=00 jf=00 k=ffffffff [1] (0037) code= BPF_JMP|BPF_JEQ|BPF_K jt=00 jf=07 k=00000000 [2] (0038) code= BPF_LD|BPF_W|BPF_IND jt=00 jf=00 k=0000000c [3] (0039) code= BPF_ALU|BPF_AND|BPF_K jt=00 jf=00 k=ffffffff [4] (003a) code= BPF_JMP|BPF_JEQ|BPF_K jt=00 jf=04 k=00000000 [5] (003b) code= BPF_LD|BPF_W|BPF_IND jt=00 jf=00 k=00000010 [6] (003c) code= BPF_ALU|BPF_AND|BPF_K jt=00 jf=00 k=ffffffff [7] (003d) code= BPF_JMP|BPF_JEQ|BPF_K jt=01 jf=00 k=00000001 [8] (003e) code= BPF_JMP|BPF_JA jt=00 jf=00 k=00000001 [9] (003f) code= BPF_RET|BPF_K jt=00 jf=00 k=00000000 [A] Line 32 loads the first 4 bytes for the 32 bytes IPv6 address, then line 33 performs the binary AND with the first 4 bytes of the mask. Line 34 evaluated false for the case 2::1 that Eric reported (since 0x2 is not 0x0). Thus, jumping to line 3f that returns reject. However, 2::1 should be allowed. This false-jump case depends on the logic we're using, for the negative logic case, the jump offset is 9 to accept it. In the positive case (ie. accept this event message if matching happens), it has to be 10 (A), to reject it. Reported-by: Eric Leblond <eric@regit.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/conntrack/bsf.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/src/conntrack/bsf.c b/src/conntrack/bsf.c
index 846b6f9..c14531e 100644
--- a/src/conntrack/bsf.c
+++ b/src/conntrack/bsf.c
@@ -562,7 +562,7 @@ bsf_add_addr_ipv6_filter(const struct nfct_filter *f,
unsigned int type)
{
unsigned int i, j, dir, attr;
- unsigned int label_continue, jf;
+ unsigned int label_continue[2], jf;
struct stack *s;
struct jump jmp;
@@ -591,21 +591,24 @@ bsf_add_addr_ipv6_filter(const struct nfct_filter *f,
}
jf = 1;
- if (f->logic[attr] == NFCT_FILTER_LOGIC_POSITIVE)
- label_continue = 1;
- else
- label_continue = 2;
+ if (f->logic[attr] == NFCT_FILTER_LOGIC_POSITIVE) {
+ label_continue[0] = 1;
+ label_continue[1] = 2;
+ } else {
+ label_continue[0] = 2;
+ label_continue[1] = 1;
+ }
j = 0;
j += nfct_bsf_load_payload_offset(this, j);
j += nfct_bsf_find_attr(this, CTA_TUPLE_ORIG, j);
- j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue[0] - j, j, s);
/* no need to access attribute payload, we are using nest-based finder
* j += nfct_bsf_add_attr_data_offset(this, j); */
j += nfct_bsf_find_attr_nest(this, CTA_TUPLE_IP, j);
- j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue[0] - j, j, s);
j += nfct_bsf_find_attr_nest(this, type, j);
- j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue[0] - j, j, s);
j += nfct_bsf_x_equal_a(this, j);
for (i = 0; i < f->l3proto_elems_ipv6[dir]; i++) {
@@ -621,7 +624,8 @@ bsf_add_addr_ipv6_filter(const struct nfct_filter *f,
j);
if (k < 3) {
j += nfct_bsf_cmp_k_stack_jf(this, ip,
- jf - j, j, s);
+ jf - j - label_continue[1],
+ j, s);
} else {
/* last word: jump if true */
j += nfct_bsf_cmp_k_stack(this, ip, jf - j,