XDP invalid mem access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi

On my virtual machine with kernel: Linux host.mydomain.cxm 5.16.9-1.el8.elrepo.x86_64 #1 SMP PREEMPT Thu Feb 10 10:45:17 EST 2022 x86_64 x86_64 x86_64 GNU/Linux

I'am trying to add vlan support ETH_P_8021Q, but when I load this code on interface:

static __always_inline int mienro_process_packet(struct xdp_md *ctx, u32 flags)
{
	const __u32 ifingress = ctx->ingress_ifindex;
	void *data_end = (void *)(long)ctx->data_end;
	void *data = (void *)(long)ctx->data;
	struct bpf_fib_lookup fib_params;
	struct ipv6hdr *ip6h = NULL;
	struct iphdr *iph = NULL;
	u16 h_proto = 0;
	u64 nh_off = 0;
	int rc;

	if (data + sizeof(struct ethhdr) > data_end)
		return XDP_DROP;

	if (((struct ethhdr *)data)->h_proto == htons(ETH_P_8021Q))
	{
		nh_off = sizeof(struct vlan_ethhdr);

		if (data + sizeof(struct vlan_ethhdr) > data_end)
			return XDP_DROP;

		h_proto = ((struct vlan_ethhdr *)data)->h_vlan_encapsulated_proto;
	}
	else
	{
		nh_off = sizeof(struct ethhdr); // layer 2 header length
		h_proto = ((struct ethhdr *)data)->h_proto;
	}

	if (data + nh_off > data_end)
		return XDP_DROP;

	if (h_proto == htons(ETH_P_IP))
	{
		iph = data + nh_off;

		if (iph + 1 > data_end)
			return XDP_DROP;

		__builtin_memset(&fib_params, 0, sizeof(fib_params));
		fib_params.ifindex = ctx->ingress_ifindex;
		fib_params.family	= AF_INET;
		fib_params.tos		= iph->tos;
		fib_params.l4_protocol	= iph->protocol;
		fib_params.sport	= 0;
		fib_params.dport	= 0;
		fib_params.tot_len	= ntohs(iph->tot_len);
		fib_params.ipv4_src	= iph->saddr;
		fib_params.ipv4_dst	= iph->daddr;
	}
	else if (h_proto == htons(ETH_P_IPV6))
	{
		ip6h = data + nh_off;

		if (ip6h + 1 > data_end)
			return XDP_DROP;

		__builtin_memset(&fib_params, 0, sizeof(fib_params));
		fib_params.ifindex = ctx->ingress_ifindex;
		fib_params.family				= AF_INET6;
		fib_params.flowinfo				= *(__be32 *)ip6h & IPV6_FLOWINFO_MASK;
		fib_params.l4_protocol			= ip6h->nexthdr;
		fib_params.sport				= 0;
		fib_params.dport				= 0;
		fib_params.tot_len				= ntohs(ip6h->payload_len);
		*((struct in6_addr *)fib_params.ipv6_src)	= ip6h->saddr;
		*((struct in6_addr *)fib_params.ipv6_dst)	= ip6h->daddr;
	}
	else
		return XDP_DROP;

	rc = bpf_fib_lookup(ctx, &fib_params, sizeof(fib_params), flags);

	if (rc == BPF_FIB_LKUP_RET_SUCCESS)
	{
		if (h_proto == htons(ETH_P_IP))
		{
			if (iph->protocol == IPPROTO_TCP)
				return XDP_PASS;

			return XDP_DROP;
		}
		else if (h_proto == htons(ETH_P_IPV6))
		{
			if (ip6h && ip6h->nexthdr == IPPROTO_TCP)
				return XDP_PASS;

			return XDP_DROP;
		}

		return XDP_DROP;
	}
	else if (rc == BPF_FIB_LKUP_RET_NOT_FWDED)
	{
		if (h_proto   == htons(ETH_P_IP))
		{
			if (iph->protocol == IPPROTO_TCP)
				return XDP_PASS;

			return XDP_DROP;
		}
		else if (h_proto == htons(ETH_P_IPV6))
		{
			if (ip6h && ip6h->nexthdr == IPPROTO_TCP)
				return XDP_PASS;

			return XDP_DROP;
		}

		return XDP_DROP;
	}

	return XDP_DROP;
}

SEC("mienro_lan") int mienro_lan_prog(struct xdp_md *ctx)
{
	return mienro_process_packet(ctx, 0);
}

SEC("mienro_lan_direct") int mienro_lan_direct_prog(struct xdp_md *ctx)
{
	return mienro_process_packet(ctx, BPF_FIB_LOOKUP_DIRECT);
}

char _license[] SEC("license") = "GPL";


... libbpf return me a good: R6 invalid mem access 'inv'.

Where I'am wrong, I'am missing some validation?
I intentionally preferred to use XDP_PASS everywhere just to simplify the code.

Also I would be curious to understand what the last two lines between these four indicate above all.

libbpf: elf: skipping unrecognized data section(19) .eh_frame
libbpf: elf: skipping relo section(20) .rel.eh_frame for section(19)
libbpf: load bpf program failed: Permission denied
btf_vmlinux is malformed

Thanks

Marco



================================================================================================================

libbpf: elf: skipping unrecognized data section(19) .eh_frame
libbpf: elf: skipping relo section(20) .rel.eh_frame for section(19)
.eh_frame
libbpf: load bpf program failed: Permission denied
libbpf: -- BEGIN DUMP LOG ---
libbpf:
btf_vmlinux is malformed
R1 type=ctx expected=fp
; SEC("mienro_lan") int mienro_lan_prog(struct xdp_md *ctx)
0: (b7) r0 = 1
; void *data_end = (void *)(long)ctx->data_end;
1: (61) r2 = *(u32 *)(r1 +4)
; void *data = (void *)(long)ctx->data;
2: (61) r6 = *(u32 *)(r1 +0)
; if (data + sizeof(struct ethhdr) > data_end)
3: (bf) r3 = r6
4: (07) r3 += 14
; if (data + sizeof(struct ethhdr) > data_end)
5: (2d) if r3 > r2 goto pc+139
 R0_w=inv1 R1=ctx(id=0,off=0,imm=0) R2_w=pkt_end(id=0,off=0,imm=0)
R3_w=pkt(id=0,off=14,r=14,imm=0) R6_w=pkt(id=0,off=0,r=14,imm=0) R10=fp0
; if (((struct ethhdr *)data)->h_proto == htons(ETH_P_8021Q))
6: (71) r3 = *(u8 *)(r6 +12)
7: (71) r7 = *(u8 *)(r6 +13)
8: (67) r7 <<= 8
9: (4f) r7 |= r3
10: (b7) r3 = 14
; if (((struct ethhdr *)data)->h_proto == htons(ETH_P_8021Q))
11: (55) if r7 != 0x81 goto pc+6
 R0_w=inv1 R1=ctx(id=0,off=0,imm=0) R2_w=pkt_end(id=0,off=0,imm=0)
R3_w=inv14 R6_w=pkt(id=0,off=0,r=14,imm=0) R7_w=inv129 R10=fp0
; if (data + sizeof(struct vlan_ethhdr) > data_end)
12: (bf) r3 = r6
13: (07) r3 += 18
;
14: (b7) r0 = 1
; if (data + sizeof(struct vlan_ethhdr) > data_end)
15: (2d) if r3 > r2 goto pc+129
 R0=inv1 R1=ctx(id=0,off=0,imm=0) R2=pkt_end(id=0,off=0,imm=0)
R3=pkt(id=0,off=18,r=18,imm=0) R6=pkt(id=0,off=0,r=18,imm=0) R7=inv129
R10=fp0
16: (b7) r3 = 18
; h_proto = ((struct vlan_ethhdr *)data)->h_vlan_encapsulated_proto;
17: (69) r7 = *(u16 *)(r6 +16)
; if (data + nh_off > data_end)
18: (0f) r6 += r3
last_idx 18 first_idx 15
regs=8 stack=0 before 17: (69) r7 = *(u16 *)(r6 +16)
regs=8 stack=0 before 16: (b7) r3 = 18
;
19: (b7) r0 = 1
; if (data + nh_off > data_end)
20: (2d) if r6 > r2 goto pc+124
 R0_w=inv1 R1=ctx(id=0,off=0,imm=0) R2=pkt_end(id=0,off=0,imm=0)
R3_w=invP18 R6_w=pkt(id=0,off=18,r=18,imm=0)
R7_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff)) R10=fp0
; if (h_proto == htons(ETH_P_IP))
21: (bf) r3 = r7
22: (57) r3 &= 65535
; if (h_proto == htons(ETH_P_IP))
23: (55) if r3 != 0x8 goto pc+31

from 23 to 55: R0=inv1 R1=ctx(id=0,off=0,imm=0)
R2=pkt_end(id=0,off=0,imm=0) R3=inv(id=0,umax_value=65535,var_off=(0x0;
0xffff)) R6=pkt(id=0,off=18,r=18,imm=0)
R7=inv(id=1,umax_value=65535,var_off=(0x0; 0xffff)) R10=fp0
;
55: (b7) r0 = 1
; else if (h_proto == htons(ETH_P_IPV6))
56: (55) if r3 != 0xdd86 goto pc+88
 R0=inv1 R1=ctx(id=0,off=0,imm=0) R2=pkt_end(id=0,off=0,imm=0) R3=inv56710
R6=pkt(id=0,off=18,r=18,imm=0) R7=inv(id=1,umax_value=65535,var_off=(0x0;
0xffff)) R10=fp0
; if (ip6h + 1 > data_end)
57: (bf) r3 = r6
58: (07) r3 += 40
;
59: (b7) r0 = 1
; if (ip6h + 1 > data_end)
60: (2d) if r3 > r2 goto pc+84
 R0_w=inv1 R1=ctx(id=0,off=0,imm=0) R2=pkt_end(id=0,off=0,imm=0)
R3_w=pkt(id=0,off=58,r=58,imm=0) R6=pkt(id=0,off=18,r=58,imm=0)
R7=inv(id=1,umax_value=65535,var_off=(0x0; 0xffff)) R10=fp0
61: (b7) r2 = 0
; __builtin_memset(&fib_params, 0, sizeof(fib_params));
62: (7b) *(u64 *)(r10 -8) = r2
last_idx 62 first_idx 56
regs=4 stack=0 before 61: (b7) r2 = 0
63: (7b) *(u64 *)(r10 -16) = r2
64: (7b) *(u64 *)(r10 -24) = r2
65: (7b) *(u64 *)(r10 -32) = r2
66: (7b) *(u64 *)(r10 -40) = r2
67: (7b) *(u64 *)(r10 -48) = r2
68: (7b) *(u64 *)(r10 -56) = r2
69: (7b) *(u64 *)(r10 -64) = r2
; fib_params.ifindex = ctx->ingress_ifindex;
70: (61) r3 = *(u32 *)(r1 +12)
71: (b7) r4 = 10
; fib_params.family = AF_INET6;
72: (73) *(u8 *)(r10 -64) = r4
; fib_params.ifindex = ctx->ingress_ifindex;
73: (63) *(u32 *)(r10 -56) = r3
; fib_params.flowinfo = *(__be32 *)ip6h & IPV6_FLOWINFO_MASK;
74: (61) r3 = *(u32 *)(r6 +0)
75: (18) r4 = 0xffffff0f
; fib_params.flowinfo = *(__be32 *)ip6h & IPV6_FLOWINFO_MASK;
77: (5f) r3 &= r4
; fib_params.flowinfo = *(__be32 *)ip6h & IPV6_FLOWINFO_MASK;
78: (63) *(u32 *)(r10 -52) = r3
; fib_params.l4_protocol = ip6h->nexthdr;
79: (71) r3 = *(u8 *)(r6 +6)
; fib_params.l4_protocol = ip6h->nexthdr;
80: (73) *(u8 *)(r10 -63) = r3
; fib_params.dport = 0;
81: (6b) *(u16 *)(r10 -60) = r2
; fib_params.sport = 0;
82: (6b) *(u16 *)(r10 -62) = r2
; fib_params.tot_len = ntohs(ip6h->payload_len);
83: (69) r2 = *(u16 *)(r6 +4)
84: (dc) r2 = be16 r2
; fib_params.tot_len = ntohs(ip6h->payload_len);
85: (6b) *(u16 *)(r10 -58) = r2
; *((struct in6_addr *)fib_params.ipv6_src) = ip6h->saddr;
86: (61) r2 = *(u32 *)(r6 +12)
87: (67) r2 <<= 32
88: (61) r3 = *(u32 *)(r6 +8)
89: (4f) r2 |= r3
90: (7b) *(u64 *)(r10 -48) = r2
91: (61) r2 = *(u32 *)(r6 +20)
92: (67) r2 <<= 32
93: (61) r3 = *(u32 *)(r6 +16)
94: (4f) r2 |= r3
95: (7b) *(u64 *)(r10 -40) = r2
; *((struct in6_addr *)fib_params.ipv6_dst) = ip6h->daddr;
96: (61) r2 = *(u32 *)(r6 +36)
97: (67) r2 <<= 32
98: (61) r3 = *(u32 *)(r6 +32)
99: (4f) r2 |= r3
100: (7b) *(u64 *)(r10 -24) = r2
101: (61) r2 = *(u32 *)(r6 +28)
102: (67) r2 <<= 32
103: (61) r3 = *(u32 *)(r6 +24)
104: (4f) r2 |= r3
105: (7b) *(u64 *)(r10 -32) = r2
;
106: (bf) r8 = r6
107: (b7) r6 = 0
108: (bf) r2 = r10
109: (07) r2 += -64
; rc = bpf_fib_lookup(ctx, &fib_params, sizeof(fib_params), flags);
110: (b7) r3 = 64
111: (b7) r4 = 0
112: (85) call bpf_fib_lookup#69
last_idx 112 first_idx 108
regs=8 stack=0 before 111: (b7) r4 = 0
regs=8 stack=0 before 110: (b7) r3 = 64
113: (bf) r1 = r0
114: (67) r1 <<= 32
115: (77) r1 >>= 32
; if (rc == BPF_FIB_LKUP_RET_SUCCESS) // FORWARD_SECTION
116: (15) if r1 == 0x4 goto pc+8
 R0_w=inv(id=3) R1_w=inv(id=0,umax_value=4294967295,var_off=(0x0;
0xffffffff)) R6=inv0 R7=inv(id=1,umax_value=65535,var_off=(0x0; 0xffff))
R8=pkt(id=0,off=18,r=58,imm=0) R10=fp0 fp-8=mmmmmmmm fp-16=mmmmmmmm
fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm fp-48=mmmmmmmm fp-56=mmmmmmmm
fp-64=mmmmmmmm
;
117: (b7) r0 = 1
; if (rc == BPF_FIB_LKUP_RET_SUCCESS) // FORWARD_SECTION
118: (55) if r1 != 0x0 goto pc+26
 R0=inv1 R1=inv0 R6=inv0 R7=inv(id=1,umax_value=65535,var_off=(0x0;
0xffff)) R8=pkt(id=0,off=18,r=58,imm=0) R10=fp0 fp-8=mmmmmmmm
fp-16=mmmmmmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm fp-48=mmmmmmmm
fp-56=mmmmmmmm fp-64=mmmmmmmm
; if (h_proto == htons(ETH_P_IP))
119: (57) r7 &= 65535
; if (h_proto == htons(ETH_P_IP))
120: (55) if r7 != 0x8 goto pc+10
 R0=inv1 R1=inv0 R6=inv0 R7_w=inv8 R8=pkt(id=0,off=18,r=58,imm=0) R10=fp0
fp-8=mmmmmmmm fp-16=mmmmmmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm
fp-48=mmmmmmmm fp-56=mmmmmmmm fp-64=mmmmmmmm
; if (iph->protocol == IPPROTO_TCP)
121: (71) r1 = *(u8 *)(r6 +9)
R6 invalid mem access 'inv'
processed 165 insns (limit 1000000) max_states_per_insn 1 total_states 10
peak_states 10 mark_read 3

libbpf: -- END LOG --



[Index of Archives]     [Linux Networking Development]     [Fedora Linux Users]     [Linux SCTP]     [DCCP]     [Gimp]     [Yosemite Campsites]

  Powered by Linux