// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 Facebook */
#include <linux/stddef.h>
#include <linux/if_ether.h>
#include <linux/ipv6.h>
#include <linux/bpf.h>
#include <linux/tcp.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_tracing.h>
struct sk_buff {
unsigned int len;
};
__u64 test_result = 0 ;
SEC("fexit/test_pkt_access" )
int BPF_PROG(test_main, struct sk_buff *skb, int ret)
{
int len;
__builtin_preserve_access_index(({
len = skb->len;
}));
if (len != 74 || ret != 0 )
return 0 ;
test_result = 1 ;
return 0 ;
}
__u64 test_result_subprog1 = 0 ;
SEC("fexit/test_pkt_access_subprog1" )
int BPF_PROG(test_subprog1, struct sk_buff *skb, int ret)
{
int len;
__builtin_preserve_access_index(({
len = skb->len;
}));
if (len != 74 || ret != 148 )
return 0 ;
test_result_subprog1 = 1 ;
return 0 ;
}
/* Though test_pkt_access_subprog2() is defined in C as:
* static _ _ attribute__ ( ( noinline ) )
* int test_pkt_access_subprog2 ( int val , volatile struct _ _ sk_buff * skb )
* {
* return skb - > len * val ;
* }
* llvm optimizations remove ' int val ' argument and generate BPF assembly :
* r0 = * ( u32 * ) ( r1 + 0 )
* w0 < < = 1
* exit
* In such case the verifier falls back to conservative and
* tracing program can access arguments and return value as u64
* instead of accurate types .
*/
struct args_subprog2 {
__u64 args[5 ];
__u64 ret;
};
__u64 test_result_subprog2 = 0 ;
SEC("fexit/test_pkt_access_subprog2" )
int test_subprog2(struct args_subprog2 *ctx)
{
struct sk_buff *skb = (void *)ctx->args[0 ];
__u64 ret;
int len;
bpf_probe_read_kernel(&len, sizeof (len),
__builtin_preserve_access_index(&skb->len));
ret = ctx->ret;
/* bpf_prog_test_load() loads "test_pkt_access.bpf.o" with
* BPF_F_TEST_RND_HI32 which randomizes upper 32 bits after BPF_ALU32
* insns . Hence after ' w0 < < = 1 ' upper bits of $ rax are random . That is
* expected and correct . Trim them .
*/
ret = (__u32) ret;
if (len != 74 || ret != 148 )
return 0 ;
test_result_subprog2 = 1 ;
return 0 ;
}
__u64 test_result_subprog3 = 0 ;
SEC("fexit/test_pkt_access_subprog3" )
int BPF_PROG(test_subprog3, int val, struct sk_buff *skb, int ret)
{
int len;
__builtin_preserve_access_index(({
len = skb->len;
}));
if (len != 74 || ret != 74 * val || val != 3 )
return 0 ;
test_result_subprog3 = 1 ;
return 0 ;
}
__u64 test_get_skb_len = 0 ;
SEC("freplace/get_skb_len" )
int new_get_skb_len(struct __sk_buff *skb)
{
int len = skb->len;
if (len != 74 )
return 0 ;
test_get_skb_len = 1 ;
return 74 ; /* original get_skb_len() returns skb->len */
}
__u64 test_get_skb_ifindex = 0 ;
SEC("freplace/get_skb_ifindex" )
int new_get_skb_ifindex(int val, struct __sk_buff *skb, int var)
{
void *data_end = (void *)(long )skb->data_end;
void *data = (void *)(long )skb->data;
struct ipv6hdr ip6, *ip6p;
int ifindex = skb->ifindex;
/* check that BPF extension can read packet via direct packet access */
if (data + 14 + sizeof (ip6) > data_end)
return 0 ;
ip6p = data + 14 ;
if (ip6p->nexthdr != 6 || ip6p->payload_len != __bpf_constant_htons(123 ))
return 0 ;
/* check that legacy packet access helper works too */
if (bpf_skb_load_bytes(skb, 14 , &ip6, sizeof (ip6)) < 0 )
return 0 ;
ip6p = &ip6;
if (ip6p->nexthdr != 6 || ip6p->payload_len != __bpf_constant_htons(123 ))
return 0 ;
if (ifindex != 1 || val != 3 || var != 1 )
return 0 ;
test_get_skb_ifindex = 1 ;
return 3 ; /* original get_skb_ifindex() returns val * ifindex * var */
}
volatile __u64 test_get_constant = 0 ;
SEC("freplace/get_constant" )
int new_get_constant(long val)
{
if (val != 123 )
return 0 ;
test_get_constant = 1 ;
return test_get_constant; /* original get_constant() returns val - 122 */
}
__u64 test_pkt_write_access_subprog = 0 ;
SEC("freplace/test_pkt_write_access_subprog" )
int new_test_pkt_write_access_subprog(struct __sk_buff *skb, __u32 off)
{
void *data = (void *)(long )skb->data;
void *data_end = (void *)(long )skb->data_end;
struct tcphdr *tcp;
if (off > sizeof (struct ethhdr) + sizeof (struct ipv6hdr))
return -1 ;
tcp = data + off;
if (tcp + 1 > data_end)
return -1 ;
/* make modifications to the packet data */
tcp->check++;
tcp->syn = 0 ;
test_pkt_write_access_subprog = 1 ;
return 0 ;
}
char _license[] SEC("license" ) = "GPL" ;
Messung V0.5 in Prozent C=95 H=90 G=92
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-10-12)
¤
*© Formatika GbR, Deutschland