diff mbox series

[libnetfilter_queue,v3] src: fix IPv6 header handling

Message ID A355CB9D-9B07-4D62-A228-A37C2660C442@apple.com
State Accepted
Delegated to: Pablo Neira
Headers show
Series [libnetfilter_queue,v3] src: fix IPv6 header handling | expand

Commit Message

Etan Kissling Feb. 9, 2021, 10:51 p.m. UTC
This corrects issues in IPv6 header handling that sometimes resulted
in an endless loop.

Signed-off-by: Etan Kissling <etan_kissling@apple.com>
---
v2: Updated loop condition to be consistent with the implementation
    ipv6_skip_exthdr() in the Linux kernel.
v3: Re-allow fetching extension headers using 'target' parameter.

 src/extra/ipv6.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

Comments

Pablo Neira Ayuso Feb. 19, 2021, 12:24 a.m. UTC | #1
On Tue, Feb 09, 2021 at 11:51:33PM +0100, Etan Kissling wrote:
> This corrects issues in IPv6 header handling that sometimes resulted
> in an endless loop.

Applied, thanks.
diff mbox series

Patch

diff --git a/src/extra/ipv6.c b/src/extra/ipv6.c
index 42c5e25..88cd77b 100644
--- a/src/extra/ipv6.c
+++ b/src/extra/ipv6.c
@@ -67,10 +67,19 @@  int nfq_ip6_set_transport_header(struct pkt_buff *pktb, struct ip6_hdr *ip6h,
 	uint8_t nexthdr = ip6h->ip6_nxt;
 	uint8_t *cur = (uint8_t *)ip6h + sizeof(struct ip6_hdr);
 
-	while (nexthdr != target) {
+	while (nexthdr == IPPROTO_HOPOPTS ||
+			nexthdr == IPPROTO_ROUTING ||
+			nexthdr == IPPROTO_FRAGMENT ||
+			nexthdr == IPPROTO_AH ||
+			nexthdr == IPPROTO_NONE ||
+			nexthdr == IPPROTO_DSTOPTS) {
 		struct ip6_ext *ip6_ext;
 		uint32_t hdrlen;
 
+		/* Extension header was requested, we're done. */
+		if (nexthdr == target)
+			break;
+
 		/* No more extensions, we're done. */
 		if (nexthdr == IPPROTO_NONE) {
 			cur = NULL;
@@ -107,11 +116,13 @@  int nfq_ip6_set_transport_header(struct pkt_buff *pktb, struct ip6_hdr *ip6h,
 		} else if (nexthdr == IPPROTO_AH)
 			hdrlen = (ip6_ext->ip6e_len + 2) << 2;
 		else
-			hdrlen = ip6_ext->ip6e_len;
+			hdrlen = (ip6_ext->ip6e_len + 1) << 3;
 
 		nexthdr = ip6_ext->ip6e_nxt;
 		cur += hdrlen;
 	}
+	if (nexthdr != target)
+		cur = NULL;
 	pktb->transport_header = cur;
 	return cur ? 1 : 0;
 }