load program: permission denied: !read_ok #1009
-
Describe the bug /*
Attempt to parse the IPv4 source address, protocol, and source port(if protocol is TCP/UDP) from the packet.
Returns 0 if there is no IPv4 header field; otherwise returns non-zero.
*/
static __always_inline int parse_ip_src_triple(struct xdp_md *ctx, __u32 *ip_src_addr, __be16 *port, __u8 *protocol) {
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
// First, parse the ethernet header.
struct ethhdr *eth = data;
if ((void *)(eth + 1) > data_end) {
return 0;
}
if (eth->h_proto != bpf_htons(ETH_P_IP)) {
// The protocol is not IPv4, so we can't parse an IPv4 source address.
return 0;
}
// printf("eth->h_proto:%d, ETH_P_IP:%d\n", eth->h_proto, bpf_htons(ETH_P_IP));
// Then parse the IP header.
struct iphdr *ip = (void *)(eth + 1);
if ((void *)(ip + 1) > data_end) {
return 0;
}
// Return the source IP address in network byte order.
*ip_src_addr = (__u32)(ip->saddr);
// Parse protocol
__u32 p = (__u32)(ip->protocol);
*protocol = (__u8)(ip->protocol);
/*switch (ip->protocol) {
case IPPROTO_TCP:
{
// Parse tcp port
struct tcphdr *tcp = (void *)(ip + 1);
if ((void *)(tcp + 1) > data_end) {
return 0;
}
*port = tcp->source;
return 1;
}
case IPPROTO_UDP:
{
// Parse udp port
struct udphdr *udp = (void *)(ip + 1);
if ((void *)(udp + 1) > data_end) {
return 0;
}
*port = udp->source;
return 1;
}
case IPPROTO_ICMP: // error occurs when execute
{
return 1;
}
default:
return 0;
}*/
//if (ip->protocol == IPPROTO_ICMP) { // outrageous! error occurs when execute
//if (ip->protocol == htons(IPPROTO_ICMP)) { // no error occurs when execute, but it can not assert if it’s IPPROTO_ICMP or not correctly
//return 1;
//}
if (ip->protocol == IPPROTO_TCP) {
// Parse tcp port
struct tcphdr *tcp = (void *)(ip + 1);
if ((void *)(tcp + 1) > data_end) {
return 0;
}
*port = tcp->source;
return 1;
}
if (ip->protocol == IPPROTO_UDP) {
// Parse udp port
struct udphdr *udp = (void *)(ip + 1);
if ((void *)(udp + 1) > data_end) {
return 0;
}
*port = udp->source;
return 1;
}
return 0;
} the final binary file executed failed with the code to judge if the protocol is IPPROTO_ICMP, throw an error below:
and it executed successfully without the code to judge IPPROTO_ICMP. To Reproduce go version: go version go1.20 linux/amd64 Expected behavior |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 5 replies
-
|
Beta Was this translation helpful? Give feedback.
I misread the error you gave, sorry. This is the important part:
This tells you:
u8
r10
is the stack pointer)r0
has not been initializedr0
is the register used for return valuesI'm guessing that your problem isn't actually in
parse_ip_src_triple
but in the caller. Try and check any place where you're writing into au8
local variable and see whether there is a way that write might be uninitialized. The fact that changing the code to usehtons(IPPROTO_ICMP)
might just be clang being very smart and eliminating your code.For the future, please post questions like this on StackOverflow.