Skip to content

Commit

Permalink
Incorrect L4 offset for IP packets with Options field
Browse files Browse the repository at this point in the history
  • Loading branch information
aka320 committed Jun 19, 2024
1 parent 32f8467 commit dc21b2f
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 15 deletions.
9 changes: 7 additions & 2 deletions connection-limit/connection_limit_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,15 +275,20 @@ int _xdp_limit_conn(struct xdp_md *ctx)

/* Check if its valid ip packet */
struct iphdr *iph = (struct iphdr *)(data + sizeof(struct ethhdr));
if (iph + 1 > data_end)
__u8 ip_hdr_len = iph->ihl * 4;

/* Validating IP Header */
if ((iph->ihl < 5 || iph->ihl > 15) ||
((__u8 *)iph + ip_hdr_len) > data_end) {
return XDP_PASS;
}

/* Ignore other than TCP packets */
if (iph->protocol != IPPROTO_TCP)
return XDP_PASS;

/* Check if its valid tcp packet */
struct tcphdr *tcph = (struct tcphdr *)(iph + 1);
struct tcphdr *tcph = (struct tcphdr *)((__u8 *)iph + ip_hdr_len);
if (tcph + 1 > data_end)
return XDP_PASS;

Expand Down
10 changes: 7 additions & 3 deletions ipfix-flow-exporter/bpf_ipfix_egress_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ void parse_ipv4(struct __sk_buff *skb, u64 l3_offset)
u16 pckt_size = data_end - data;

struct iphdr *iph = data + l3_offset;
u8 ip_hdr_len = (iph->ihl * 4);

if (iph > data_end)
return;
Expand All @@ -238,13 +239,16 @@ void parse_ipv4(struct __sk_buff *skb, u64 l3_offset)
u16 control_bit = 0;
u16 icmp_type = 0;

if (iph + 1 > data_end)
/* Validating IP Header */
if ((iph->ihl < 5 || iph->ihl > 15) ||
((u8 *)iph + ip_hdr_len) > data_end) {
return;
}

if(iph->protocol == ICMP)
parse_icmp_type(iph+1, data_end, &icmp_type);
parse_icmp_type(((u8 *)iph + ip_hdr_len), data_end, &icmp_type);

parse_port(iph+1, data_end, iph->protocol, &dport, &sport, &control_bit);
parse_port(((u8 *)iph + ip_hdr_len), data_end, iph->protocol, &dport, &sport, &control_bit);

memset(&flow_key, 0, sizeof(flow_key));
flow_key.sa = iph->saddr;
Expand Down
10 changes: 7 additions & 3 deletions ipfix-flow-exporter/bpf_ipfix_ingress_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ void parse_ipv4(struct __sk_buff *skb, u64 l3_offset)
u16 pckt_size = data_end - data;

struct iphdr *iph = data + l3_offset;
u8 ip_hdr_len = (iph->ihl * 4);

if (iph > data_end)
return;
Expand All @@ -238,13 +239,16 @@ void parse_ipv4(struct __sk_buff *skb, u64 l3_offset)
u16 control_bit = 0;
u16 icmp_type = 0;

if (iph + 1 > data_end)
/* Validating IP Header */
if ((iph->ihl < 5 || iph->ihl > 15) ||
((u8 *)iph + ip_hdr_len) > data_end) {
return;
}

if(iph->protocol == ICMP)
parse_icmp_type(iph+1, data_end, &icmp_type);
parse_icmp_type(((u8 *)iph + ip_hdr_len), data_end, &icmp_type);

parse_port(iph+1, data_end, iph->protocol, &dport, &sport, &control_bit);
parse_port(((u8 *)iph + ip_hdr_len), data_end, iph->protocol, &dport, &sport, &control_bit);

memset(&flow_key, 0, sizeof(flow_key));
flow_key.sa = iph->saddr;
Expand Down
7 changes: 6 additions & 1 deletion ratelimiting/ratelimiting_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,13 @@ static __always_inline int _xdp_ratelimit(struct xdp_md *ctx)

/* Ignore other than IP packets */
struct iphdr *iph = data + sizeof(struct ethhdr);
if (iph + 1 > data_end)
uint8_t ip_hdr_len = iph->ihl * 4;

/* Validating IP Header */
if ((iph->ihl < 5 || iph->ihl > 15) ||
((uint8_t *)iph + ip_hdr_len) > data_end) {
return XDP_PASS;
}

/* Ignore other than TCP packets */
if (iph->protocol != IPPROTO_TCP)
Expand Down
8 changes: 5 additions & 3 deletions traffic-mirroring/mirroring_egress_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ static __always_inline int egress_redirect(struct __sk_buff *skb)
void *data_end = (void *)(long)skb->data_end;

const int l3_off = ETH_HLEN; // IP header offset
const int l4_off = l3_off + sizeof(struct iphdr); // TCP header offset
struct iphdr *iph = (struct iphdr *)(data + l3_off);
const int l4_off = l3_off + (iph->ihl * 4); // TCP header offset

struct ethhdr *eth = data;
int l7_off;
Expand All @@ -142,10 +143,11 @@ static __always_inline int egress_redirect(struct __sk_buff *skb)
return TC_ACT_OK;
}

if (data + l4_off > data_end) {
/* Validating IP Header */
if ((iph->ihl < 5 || iph->ihl > 15) ||
(data + l4_off > data_end)) {
return TC_ACT_OK; // Not our packet, handover to kernel
}
struct iphdr *iph = (struct iphdr *)(data + l3_off);

if (iph->protocol == IPPROTO_TCP) {
l7_off = l4_off + sizeof(struct tcphdr); // L7 (e.g. HTTP) header offset
Expand Down
8 changes: 5 additions & 3 deletions traffic-mirroring/mirroring_ingress_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ static __always_inline int ingress_redirect(struct __sk_buff *skb)
void *data_end = (void *)(long)skb->data_end;

const int l3_off = ETH_HLEN; // IP header offset
const int l4_off = l3_off + sizeof(struct iphdr); // TCP header offset
struct iphdr *iph = (struct iphdr *)(data + l3_off);
const int l4_off = l3_off + (iph->ihl * 4); // TCP header offset // TCP header offset

struct ethhdr *eth = data;
int l7_off;
Expand All @@ -141,10 +142,11 @@ static __always_inline int ingress_redirect(struct __sk_buff *skb)
return TC_ACT_OK;
}

if (data + l4_off > data_end) {
/* Validating IP Header */
if ((iph->ihl < 5 || iph->ihl > 15) ||
(data + l4_off > data_end)) {
return TC_ACT_OK; // Not our packet, handover to kernel
}
struct iphdr *iph = (struct iphdr *)(data + l3_off);

if (iph->protocol == IPPROTO_TCP) {
l7_off = l4_off + sizeof(struct tcphdr); // L7 (e.g. HTTP) header offset
Expand Down

0 comments on commit dc21b2f

Please sign in to comment.