17bd1590dSMartin KaFai Lau // SPDX-License-Identifier: GPL-2.0
27bd1590dSMartin KaFai Lau /* Copyright (c) 2021 Facebook */
3c1ff181fSKumar Kartikeya Dwivedi #include <vmlinux.h>
47bd1590dSMartin KaFai Lau #include <bpf/bpf_helpers.h>
5*8e9af821SJiri Olsa #include "../bpf_testmod/bpf_testmod_kfunc.h"
6c1ff181fSKumar Kartikeya Dwivedi 
7c22bdd28SAndrii Nakryiko SEC("tc")
kfunc_call_test4(struct __sk_buff * skb)8be6b5c10SIlya Leoshkevich int kfunc_call_test4(struct __sk_buff *skb)
9be6b5c10SIlya Leoshkevich {
10be6b5c10SIlya Leoshkevich 	struct bpf_sock *sk = skb->sk;
11be6b5c10SIlya Leoshkevich 	long tmp;
12be6b5c10SIlya Leoshkevich 
13be6b5c10SIlya Leoshkevich 	if (!sk)
14be6b5c10SIlya Leoshkevich 		return -1;
15be6b5c10SIlya Leoshkevich 
16be6b5c10SIlya Leoshkevich 	sk = bpf_sk_fullsock(sk);
17be6b5c10SIlya Leoshkevich 	if (!sk)
18be6b5c10SIlya Leoshkevich 		return -1;
19be6b5c10SIlya Leoshkevich 
20be6b5c10SIlya Leoshkevich 	tmp = bpf_kfunc_call_test4(-3, -30, -200, -1000);
21be6b5c10SIlya Leoshkevich 	return (tmp >> 32) + tmp;
22be6b5c10SIlya Leoshkevich }
23be6b5c10SIlya Leoshkevich 
24be6b5c10SIlya Leoshkevich SEC("tc")
kfunc_call_test2(struct __sk_buff * skb)257bd1590dSMartin KaFai Lau int kfunc_call_test2(struct __sk_buff *skb)
267bd1590dSMartin KaFai Lau {
277bd1590dSMartin KaFai Lau 	struct bpf_sock *sk = skb->sk;
287bd1590dSMartin KaFai Lau 
297bd1590dSMartin KaFai Lau 	if (!sk)
307bd1590dSMartin KaFai Lau 		return -1;
317bd1590dSMartin KaFai Lau 
327bd1590dSMartin KaFai Lau 	sk = bpf_sk_fullsock(sk);
337bd1590dSMartin KaFai Lau 	if (!sk)
347bd1590dSMartin KaFai Lau 		return -1;
357bd1590dSMartin KaFai Lau 
367bd1590dSMartin KaFai Lau 	return bpf_kfunc_call_test2((struct sock *)sk, 1, 2);
377bd1590dSMartin KaFai Lau }
387bd1590dSMartin KaFai Lau 
39c22bdd28SAndrii Nakryiko SEC("tc")
kfunc_call_test1(struct __sk_buff * skb)407bd1590dSMartin KaFai Lau int kfunc_call_test1(struct __sk_buff *skb)
417bd1590dSMartin KaFai Lau {
427bd1590dSMartin KaFai Lau 	struct bpf_sock *sk = skb->sk;
437bd1590dSMartin KaFai Lau 	__u64 a = 1ULL << 32;
447bd1590dSMartin KaFai Lau 	__u32 ret;
457bd1590dSMartin KaFai Lau 
467bd1590dSMartin KaFai Lau 	if (!sk)
477bd1590dSMartin KaFai Lau 		return -1;
487bd1590dSMartin KaFai Lau 
497bd1590dSMartin KaFai Lau 	sk = bpf_sk_fullsock(sk);
507bd1590dSMartin KaFai Lau 	if (!sk)
517bd1590dSMartin KaFai Lau 		return -1;
527bd1590dSMartin KaFai Lau 
537bd1590dSMartin KaFai Lau 	a = bpf_kfunc_call_test1((struct sock *)sk, 1, a | 2, 3, a | 4);
547bd1590dSMartin KaFai Lau 	ret = a >> 32;   /* ret should be 2 */
557bd1590dSMartin KaFai Lau 	ret += (__u32)a; /* ret should be 12 */
567bd1590dSMartin KaFai Lau 
577bd1590dSMartin KaFai Lau 	return ret;
587bd1590dSMartin KaFai Lau }
597bd1590dSMartin KaFai Lau 
60c1ff181fSKumar Kartikeya Dwivedi SEC("tc")
kfunc_call_test_ref_btf_id(struct __sk_buff * skb)61c1ff181fSKumar Kartikeya Dwivedi int kfunc_call_test_ref_btf_id(struct __sk_buff *skb)
62c1ff181fSKumar Kartikeya Dwivedi {
63c1ff181fSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *pt;
64c1ff181fSKumar Kartikeya Dwivedi 	unsigned long s = 0;
65c1ff181fSKumar Kartikeya Dwivedi 	int ret = 0;
66c1ff181fSKumar Kartikeya Dwivedi 
67c1ff181fSKumar Kartikeya Dwivedi 	pt = bpf_kfunc_call_test_acquire(&s);
68c1ff181fSKumar Kartikeya Dwivedi 	if (pt) {
69c1ff181fSKumar Kartikeya Dwivedi 		if (pt->a != 42 || pt->b != 108)
70c1ff181fSKumar Kartikeya Dwivedi 			ret = -1;
71c1ff181fSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(pt);
72c1ff181fSKumar Kartikeya Dwivedi 	}
73c1ff181fSKumar Kartikeya Dwivedi 	return ret;
74c1ff181fSKumar Kartikeya Dwivedi }
75c1ff181fSKumar Kartikeya Dwivedi 
76c1ff181fSKumar Kartikeya Dwivedi SEC("tc")
kfunc_call_test_pass(struct __sk_buff * skb)77c1ff181fSKumar Kartikeya Dwivedi int kfunc_call_test_pass(struct __sk_buff *skb)
78c1ff181fSKumar Kartikeya Dwivedi {
79c1ff181fSKumar Kartikeya Dwivedi 	struct prog_test_pass1 p1 = {};
80c1ff181fSKumar Kartikeya Dwivedi 	struct prog_test_pass2 p2 = {};
81c1ff181fSKumar Kartikeya Dwivedi 	short a = 0;
82c1ff181fSKumar Kartikeya Dwivedi 	__u64 b = 0;
83c1ff181fSKumar Kartikeya Dwivedi 	long c = 0;
84c1ff181fSKumar Kartikeya Dwivedi 	char d = 0;
85c1ff181fSKumar Kartikeya Dwivedi 	int e = 0;
86c1ff181fSKumar Kartikeya Dwivedi 
87c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_pass_ctx(skb);
88c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_pass1(&p1);
89c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_pass2(&p2);
90c1ff181fSKumar Kartikeya Dwivedi 
91c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&a, sizeof(a));
92c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&b, sizeof(b));
93c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&c, sizeof(c));
94c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&d, sizeof(d));
95c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&e, sizeof(e));
96c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_fail2(&b, -1);
97c1ff181fSKumar Kartikeya Dwivedi 
98c1ff181fSKumar Kartikeya Dwivedi 	return 0;
99c1ff181fSKumar Kartikeya Dwivedi }
100c1ff181fSKumar Kartikeya Dwivedi 
101fb66223aSBenjamin Tissoires struct syscall_test_args {
102fb66223aSBenjamin Tissoires 	__u8 data[16];
103fb66223aSBenjamin Tissoires 	size_t size;
104fb66223aSBenjamin Tissoires };
105fb66223aSBenjamin Tissoires 
106fb66223aSBenjamin Tissoires SEC("syscall")
kfunc_syscall_test(struct syscall_test_args * args)107fb66223aSBenjamin Tissoires int kfunc_syscall_test(struct syscall_test_args *args)
108fb66223aSBenjamin Tissoires {
109fb66223aSBenjamin Tissoires 	const long size = args->size;
110fb66223aSBenjamin Tissoires 
111fb66223aSBenjamin Tissoires 	if (size > sizeof(args->data))
112fb66223aSBenjamin Tissoires 		return -7; /* -E2BIG */
113fb66223aSBenjamin Tissoires 
114fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(&args->data, sizeof(args->data));
115fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(&args->data, sizeof(*args));
116fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(&args->data, size);
117fb66223aSBenjamin Tissoires 
118fb66223aSBenjamin Tissoires 	return 0;
119fb66223aSBenjamin Tissoires }
120fb66223aSBenjamin Tissoires 
121fb66223aSBenjamin Tissoires SEC("syscall")
kfunc_syscall_test_null(struct syscall_test_args * args)122fb66223aSBenjamin Tissoires int kfunc_syscall_test_null(struct syscall_test_args *args)
123fb66223aSBenjamin Tissoires {
124fb66223aSBenjamin Tissoires 	/* Must be called with args as a NULL pointer
125fb66223aSBenjamin Tissoires 	 * we do not check for it to have the verifier consider that
126fb66223aSBenjamin Tissoires 	 * the pointer might not be null, and so we can load it.
127fb66223aSBenjamin Tissoires 	 *
128fb66223aSBenjamin Tissoires 	 * So the following can not be added:
129fb66223aSBenjamin Tissoires 	 *
130fb66223aSBenjamin Tissoires 	 * if (args)
131fb66223aSBenjamin Tissoires 	 *      return -22;
132fb66223aSBenjamin Tissoires 	 */
133fb66223aSBenjamin Tissoires 
134fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(args, 0);
135fb66223aSBenjamin Tissoires 
136fb66223aSBenjamin Tissoires 	return 0;
137fb66223aSBenjamin Tissoires }
138fb66223aSBenjamin Tissoires 
13922ed8d5aSBenjamin Tissoires SEC("tc")
kfunc_call_test_get_mem(struct __sk_buff * skb)14022ed8d5aSBenjamin Tissoires int kfunc_call_test_get_mem(struct __sk_buff *skb)
14122ed8d5aSBenjamin Tissoires {
14222ed8d5aSBenjamin Tissoires 	struct prog_test_ref_kfunc *pt;
14322ed8d5aSBenjamin Tissoires 	unsigned long s = 0;
14422ed8d5aSBenjamin Tissoires 	int *p = NULL;
14522ed8d5aSBenjamin Tissoires 	int ret = 0;
14622ed8d5aSBenjamin Tissoires 
14722ed8d5aSBenjamin Tissoires 	pt = bpf_kfunc_call_test_acquire(&s);
14822ed8d5aSBenjamin Tissoires 	if (pt) {
14922ed8d5aSBenjamin Tissoires 		p = bpf_kfunc_call_test_get_rdwr_mem(pt, 2 * sizeof(int));
15022ed8d5aSBenjamin Tissoires 		if (p) {
15122ed8d5aSBenjamin Tissoires 			p[0] = 42;
15222ed8d5aSBenjamin Tissoires 			ret = p[1]; /* 108 */
15322ed8d5aSBenjamin Tissoires 		} else {
15422ed8d5aSBenjamin Tissoires 			ret = -1;
15522ed8d5aSBenjamin Tissoires 		}
15622ed8d5aSBenjamin Tissoires 
15722ed8d5aSBenjamin Tissoires 		if (ret >= 0) {
15822ed8d5aSBenjamin Tissoires 			p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int));
15922ed8d5aSBenjamin Tissoires 			if (p)
16022ed8d5aSBenjamin Tissoires 				ret = p[0]; /* 42 */
16122ed8d5aSBenjamin Tissoires 			else
16222ed8d5aSBenjamin Tissoires 				ret = -1;
16322ed8d5aSBenjamin Tissoires 		}
16422ed8d5aSBenjamin Tissoires 
16522ed8d5aSBenjamin Tissoires 		bpf_kfunc_call_test_release(pt);
16622ed8d5aSBenjamin Tissoires 	}
16722ed8d5aSBenjamin Tissoires 	return ret;
16822ed8d5aSBenjamin Tissoires }
16922ed8d5aSBenjamin Tissoires 
1706aed15e3SDavid Vernet SEC("tc")
kfunc_call_test_static_unused_arg(struct __sk_buff * skb)1716aed15e3SDavid Vernet int kfunc_call_test_static_unused_arg(struct __sk_buff *skb)
1726aed15e3SDavid Vernet {
1736aed15e3SDavid Vernet 
1746aed15e3SDavid Vernet 	u32 expected = 5, actual;
1756aed15e3SDavid Vernet 
1766aed15e3SDavid Vernet 	actual = bpf_kfunc_call_test_static_unused_arg(expected, 0xdeadbeef);
1776aed15e3SDavid Vernet 	return actual != expected ? -1 : 0;
1786aed15e3SDavid Vernet }
1796aed15e3SDavid Vernet 
1807bd1590dSMartin KaFai Lau char _license[] SEC("license") = "GPL";
181