summaryrefslogtreecommitdiff
path: root/tools/testing
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing')
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_aggregate_arg.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/progs/verifier_aggregate_arg.c b/tools/testing/selftests/bpf/progs/verifier_aggregate_arg.c
index fc7c1b18bc40..b0ecccede47e 100644
--- a/tools/testing/selftests/bpf/progs/verifier_aggregate_arg.c
+++ b/tools/testing/selftests/bpf/progs/verifier_aggregate_arg.c
@@ -7,6 +7,131 @@
#define MIX_A 0xdeadbeefcafef00dULL
#define MIX_B 0x0123456789abcdefULL
+struct pair {
+ __u64 lo;
+ __u64 hi;
+};
+
+struct small {
+ __u32 a;
+ __u32 b;
+};
+
+union upair {
+ __u64 halves[2];
+ struct {
+ __u64 lo;
+ __u64 hi;
+ } parts;
+};
+
+struct with_ptr {
+ void *p;
+ __u64 x;
+};
+
+static __noinline __u64 take_pair(int a, struct pair p, int c)
+{
+ return (__u64)a + p.lo + p.hi + c;
+}
+
+SEC("tc")
+__success __retval(0)
+int aggregate_arg_static_struct_c_test(struct __sk_buff *skb)
+{
+ __u64 a = skb->len ^ MIX_A;
+ __u64 b = skb->len ^ MIX_B;
+ struct pair p = { .lo = a, .hi = b };
+
+ if (take_pair(1, p, 2) != a + b + 3)
+ return 1;
+
+ return 0;
+}
+
+#if defined(__clang__)
+
+__noinline __u64 take_pair_global(int a, struct pair p, int c)
+{
+ return (__u64)a + p.lo + p.hi + c;
+}
+
+SEC("tc")
+__success __retval(0)
+int aggregate_arg_global_struct_c_test(struct __sk_buff *skb)
+{
+ __u64 a = skb->len ^ MIX_A;
+ __u64 b = skb->len ^ MIX_B;
+ struct pair p = { .lo = a, .hi = b };
+
+ if (take_pair_global(1, p, 2) != a + b + 3)
+ return 1;
+
+ return 0;
+}
+
+__noinline __u64 take_two_pairs_global(struct pair p, struct pair q, int d)
+{
+ return p.lo + p.hi + q.lo + q.hi + d;
+}
+
+SEC("tc")
+__success __retval(0)
+int aggregate_arg_two_structs_c_test(struct __sk_buff *skb)
+{
+ __u64 a = skb->len ^ MIX_A;
+ __u64 b = skb->len ^ MIX_B;
+ struct pair p = { .lo = a, .hi = b };
+ struct pair q = { .lo = a + 1, .hi = b + 2 };
+
+ if (take_two_pairs_global(p, q, 3) != 2 * a + 2 * b + 6)
+ return 1;
+
+ return 0;
+}
+
+__noinline __u64 take_small_global(int a, struct small s, int c)
+{
+ return (__u64)a + s.a + s.b + c;
+}
+
+SEC("tc")
+__success __retval(0)
+int aggregate_arg_small_struct_c_test(struct __sk_buff *skb)
+{
+ __u32 a = skb->len ^ (__u32)MIX_A;
+ __u32 b = skb->len ^ (__u32)MIX_B;
+ struct small s = { .a = a, .b = b };
+
+ if (take_small_global(1, s, 2) != (__u64)a + b + 3)
+ return 1;
+
+ return 0;
+}
+
+__noinline __u64 take_upair_global(int a, union upair u, int c)
+{
+ return (__u64)a + u.parts.lo + u.parts.hi + c;
+}
+
+SEC("tc")
+__success __retval(0)
+int aggregate_arg_union_c_test(struct __sk_buff *skb)
+{
+ __u64 a = skb->len ^ MIX_A;
+ __u64 b = skb->len ^ MIX_B;
+ union upair u;
+
+ u.halves[0] = a;
+ u.halves[1] = b;
+ if (take_upair_global(1, u, 2) != a + b + 3)
+ return 1;
+
+ return 0;
+}
+
+#endif
+
#ifdef __SIZEOF_INT128__
typedef unsigned __int128 u128;
@@ -32,4 +157,44 @@ int aggregate_arg_int128_c_test(struct __sk_buff *skb)
#endif /* __SIZEOF_INT128__ */
+#if defined(__BPF_FEATURE_STACK_ARGUMENT)
+
+static __noinline __u64 take_spilled_pair(int a, int b, int c, int d, struct pair p)
+{
+ return (__u64)a + b + c + d + p.lo + p.hi;
+}
+
+SEC("tc")
+__arch_x86_64 __arch_arm64
+__load_if_JITed()
+__success __retval(0)
+int aggregate_arg_spilled_struct_c_test(struct __sk_buff *skb)
+{
+ __u64 a = skb->len ^ MIX_A;
+ __u64 b = skb->len ^ MIX_B;
+ struct pair p = { .lo = a, .hi = b };
+ int n = skb->len;
+
+ if (take_spilled_pair(n, n + 1, n + 2, n + 3, p) != a + b + 4 * n + 6)
+ return 1;
+
+ return 0;
+}
+
+#endif
+
+__noinline __u64 take_with_ptr_global(struct with_ptr s)
+{
+ return s.x;
+}
+
+SEC("tc")
+__failure __msg("type STRUCT in take_with_ptr_global() is not composed of scalars")
+int aggregate_arg_ptr_member_fail(struct __sk_buff *skb)
+{
+ struct with_ptr s = { .p = skb, .x = skb->len };
+
+ return take_with_ptr_global(s);
+}
+
char _license[] SEC("license") = "GPL";