From 4b6df760e3b19ec522b66cbbb5b280fec7c0405b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 25 Jul 2012 11:41:35 +0200 Subject: 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 Signed-off-by: Pablo Neira Ayuso --- src/conntrack/bsf.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'src') 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, -- cgit v1.2.3