xdp-tutorial
xdp-tutorial copied to clipboard
call bpf_skb_store_bytes, but invalid mem access
last_idx 475 first_idx 448 regs=4 stack=0 before 474: (b7) r2 = 35 476: (bf) r7 = r10 477: (07) r7 += -96 478: (bf) r1 = r6 479: (b7) r2 = 42 480: (bf) r3 = r7 481: (b7) r4 = 14 482: (85) call bpf_skb_load_bytes#26 last_idx 482 first_idx 476 regs=10 stack=0 before 481: (b7) r4 = 14 483: (b7) r1 = 825307441 484: (63) *(u32 *)(r10 -96) = r1 485: (79) r2 = *(u64 *)(r10 -240) 486: (61) r1 = *(u32 *)(r2 +26) R2 invalid mem access 'inv' processed 450 insns (limit 1000000) max_states_per_insn 0 total_states 20 peak_states 20 mark_read 13
HINT: The invalid mem access 'inv' error can happen if you try to dereference memory without first using bpf_probe_read_kernel() to copy it to the BPF stack. Sometimes the bpf_probe_read_kernel() is automatic by the bcc rewriter, other times you'll need to be explicit.
Traceback (most recent call last):
File "./main.py", line 73, in
my source code: #define L3_CSUM_OFF (ETH_HLEN + offsetof(struct iphdr, check)) #define IP_SRC_OFF (ETH_HLEN + offsetof(struct iphdr, saddr)) #define IP_DST_OFF (ETH_HLEN + offsetof(struct iphdr, daddr)) #define IP_TOTLEN_OFF (ETH_HLEN + offsetof(struct iphdr, tot_len))
#define L4_PORT_OFF (ETH_HLEN + sizeof(struct iphdr) + offsetof(struct udphdr, dest )) #define L4_SRCPORT_OFF (ETH_HLEN + sizeof(struct iphdr) + offsetof(struct udphdr, source )) #define L4_CSUM_OFF (ETH_HLEN + sizeof(struct iphdr) + offsetof(struct udphdr, check)) #define L4_LEN_OFF (ETH_HLEN + sizeof(struct iphdr) + offsetof(struct udphdr, len ))
#define L4_RELAY_OFF ((ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr)))
struct relay_header { __u32 tag; __u32 srcIp; __u16 srcPort; __u16 dstPort; __u16 checksum; }attribute((packed));
#ifndef memcpy #define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) #endif
static inline int mutate_packet(struct __sk_buff *skb, __be32 target_addr, __be16 target_port, bool fwd_packet) { int ret; void *data = (void *)(long)skb->data; void *data_end = (void *)(long)skb->data_end; struct ethhdr *eth = data; struct iphdr *ip = (data + sizeof(struct ethhdr)); struct udphdr *udp = (data + sizeof(struct ethhdr) + sizeof(struct iphdr)); struct bpf_fib_lookup fib_params; struct relay_header rh; int rh_size = sizeof(rh);
// return early if not enough data
if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) > data_end){
return -1;
}
// only IP packets are allowed
if (eth->h_proto != bpf_htons(ETH_P_IP)){
return -1;
}
// grab original destination addr
__u32 src_ip = ip->saddr;
__u32 dst_ip = ip->daddr;
__be16 tot_len = ip->tot_len;
__be16 new_tot = bpf_htons(bpf_ntohs(tot_len) + rh_size);
bpf_trace_printk("ip totlen:0x%x, new_tot:0x%x", tot_len, new_tot);
__be16 dst_port = udp->dest;
__be16 src_port = udp->source;
__be16 udp_len = udp->len;
__be16 new_udp_len = bpf_htons(bpf_ntohs(udp_len) + rh_size);
bpf_trace_printk("udp_len:0x%x, new_len:0x%x", udp_len, new_udp_len);
if (fwd_packet) {
__builtin_memset(&fib_params, 0, sizeof(fib_params));
fib_params.family = AF_INET;
fib_params.tos = ip->tos;
fib_params.l4_protocol = ip->protocol;
fib_params.sport = 0;
fib_params.dport = 0;
fib_params.tot_len = bpf_ntohs(ip->tot_len);
fib_params.ipv4_src = src_ip;
fib_params.ipv4_dst = target_addr;
fib_params.ifindex = skb->ingress_ifindex;
ret = bpf_fib_lookup(skb, &fib_params, sizeof(fib_params), BPF_FIB_LOOKUP_DIRECT);
if (ret != BPF_FIB_LKUP_RET_SUCCESS) {
#ifdef DEBUG
bpf_trace_printk("fib lookup result: %lu\n", ret);
bpf_trace_printk("fib lookup src_ip= %lu dst_ip= %lu\n", src_ip, target_addr);
#endif
return -1;
}
bpf_trace_printk("before adjust tail, len: %d.", skb->data_end - skb->data);
ret = bpf_skb_adjust_room(skb, rh_size, BPF_ADJ_ROOM_NET, BPF_F_ADJ_ROOM_ENCAP_L3_IPV4|BPF_F_ADJ_ROOM_ENCAP_L4_UDP);
if (ret != 0) {
bpf_trace_printk("adjust tail fail:%d.", ret);
return -1;
}
bpf_trace_printk("after adjust tail, len: %d.", skb->data_end - skb->data);
// set smac/dmac addr
bpf_skb_store_bytes(skb, 0, &fib_params.dmac, sizeof(fib_params.dmac), 0);
bpf_skb_store_bytes(skb, ETH_ALEN, &fib_params.smac, sizeof(fib_params.smac), 0);
}
#ifdef DEBUG
bpf_trace_printk("csum rewrite dst_ip= %lu target_addr= %lu\n", dst_ip, target_addr);
bpf_trace_printk("csum rewrite src_ip= %lu dst_ip= %lu\n", src_ip, dst_ip);
bpf_trace_printk("csum rewrite dst_port= %lu target_port= %lu\n", dst_port, target_port);
#endif
// recalc checksum
bpf_l4_csum_replace(skb, L4_CSUM_OFF, dst_ip, target_addr, sizeof(target_addr));
bpf_l4_csum_replace(skb, L4_CSUM_OFF, src_ip, dst_ip, sizeof(dst_ip));
bpf_l4_csum_replace(skb, L4_CSUM_OFF, dst_port, target_port, sizeof(target_port));
bpf_l4_csum_replace(skb, L4_CSUM_OFF, src_port, dst_port, sizeof(dst_port));
bpf_l4_csum_replace(skb, L4_CSUM_OFF, udp_len, new_udp_len, sizeof(new_udp_len));
bpf_l3_csum_replace(skb, L3_CSUM_OFF, dst_ip, target_addr, sizeof(target_addr));
bpf_l3_csum_replace(skb, L3_CSUM_OFF, src_ip, dst_ip, sizeof(dst_ip));
bpf_l3_csum_replace(skb, L3_CSUM_OFF, tot_len, new_tot, sizeof(tot_len));
// set src/dst addr
bpf_skb_store_bytes(skb, IP_TOTLEN_OFF, &new_tot, sizeof(tot_len), 0);
bpf_skb_store_bytes(skb, IP_SRC_OFF, &dst_ip, sizeof(dst_ip), 0);
bpf_skb_store_bytes(skb, IP_DST_OFF, &target_addr, sizeof(target_addr), 0);
bpf_skb_store_bytes(skb, L4_PORT_OFF, &target_port, sizeof(target_port), 0);
bpf_skb_store_bytes(skb, L4_SRCPORT_OFF, &dst_port, sizeof(dst_port), 0);
bpf_skb_store_bytes(skb, L4_LEN_OFF, &new_udp_len, sizeof(udp_len), 0);
bpf_skb_load_bytes(skb, IP_TOTLEN_OFF, &tot_len, sizeof(tot_len));
bpf_skb_load_bytes(skb, L4_LEN_OFF, &udp_len, sizeof(udp_len));
bpf_trace_printk("rewrite tot_len:0x%x, udp_len:0x%x", tot_len, udp_len);
bpf_skb_load_bytes(skb, L4_RELAY_OFF, &rh, sizeof(rh));
rh.tag = 0x31313131;
rh.srcIp = ip->saddr;
rh.srcPort = udp->source;
rh.dstPort = target_port;
rh.checksum = 0;
bpf_skb_load_bytes(skb, L4_RELAY_OFF, &rh, sizeof(rh));
if (fwd_packet){
// clone packet, put it on interface found in fib
bpf_trace_printk("fwd 1 packet, ifindex:%d\n", fib_params.ifindex);
return bpf_clone_redirect(skb, fib_params.ifindex, 0);
}
return 0;
}
I want to grow 14 bytes in the packet's buf , and rewrite my content .