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>
57bd1590dSMartin KaFai Lau 
67bd1590dSMartin KaFai Lau extern int bpf_kfunc_call_test2(struct sock *sk, __u32 a, __u32 b) __ksym;
77bd1590dSMartin KaFai Lau extern __u64 bpf_kfunc_call_test1(struct sock *sk, __u32 a, __u64 b,
87bd1590dSMartin KaFai Lau 				  __u32 c, __u64 d) __ksym;
97bd1590dSMartin KaFai Lau 
10c1ff181fSKumar Kartikeya Dwivedi extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym;
11c1ff181fSKumar Kartikeya Dwivedi extern void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p) __ksym;
12c1ff181fSKumar Kartikeya Dwivedi extern void bpf_kfunc_call_test_pass_ctx(struct __sk_buff *skb) __ksym;
13c1ff181fSKumar Kartikeya Dwivedi extern void bpf_kfunc_call_test_pass1(struct prog_test_pass1 *p) __ksym;
14c1ff181fSKumar Kartikeya Dwivedi extern void bpf_kfunc_call_test_pass2(struct prog_test_pass2 *p) __ksym;
15c1ff181fSKumar Kartikeya Dwivedi extern void bpf_kfunc_call_test_mem_len_pass1(void *mem, int len) __ksym;
16c1ff181fSKumar Kartikeya Dwivedi extern void bpf_kfunc_call_test_mem_len_fail2(__u64 *mem, int len) __ksym;
17*22ed8d5aSBenjamin Tissoires extern int *bpf_kfunc_call_test_get_rdwr_mem(struct prog_test_ref_kfunc *p, const int rdwr_buf_size) __ksym;
18*22ed8d5aSBenjamin Tissoires extern int *bpf_kfunc_call_test_get_rdonly_mem(struct prog_test_ref_kfunc *p, const int rdonly_buf_size) __ksym;
19c1ff181fSKumar Kartikeya Dwivedi 
20c22bdd28SAndrii Nakryiko SEC("tc")
217bd1590dSMartin KaFai Lau int kfunc_call_test2(struct __sk_buff *skb)
227bd1590dSMartin KaFai Lau {
237bd1590dSMartin KaFai Lau 	struct bpf_sock *sk = skb->sk;
247bd1590dSMartin KaFai Lau 
257bd1590dSMartin KaFai Lau 	if (!sk)
267bd1590dSMartin KaFai Lau 		return -1;
277bd1590dSMartin KaFai Lau 
287bd1590dSMartin KaFai Lau 	sk = bpf_sk_fullsock(sk);
297bd1590dSMartin KaFai Lau 	if (!sk)
307bd1590dSMartin KaFai Lau 		return -1;
317bd1590dSMartin KaFai Lau 
327bd1590dSMartin KaFai Lau 	return bpf_kfunc_call_test2((struct sock *)sk, 1, 2);
337bd1590dSMartin KaFai Lau }
347bd1590dSMartin KaFai Lau 
35c22bdd28SAndrii Nakryiko SEC("tc")
367bd1590dSMartin KaFai Lau int kfunc_call_test1(struct __sk_buff *skb)
377bd1590dSMartin KaFai Lau {
387bd1590dSMartin KaFai Lau 	struct bpf_sock *sk = skb->sk;
397bd1590dSMartin KaFai Lau 	__u64 a = 1ULL << 32;
407bd1590dSMartin KaFai Lau 	__u32 ret;
417bd1590dSMartin KaFai Lau 
427bd1590dSMartin KaFai Lau 	if (!sk)
437bd1590dSMartin KaFai Lau 		return -1;
447bd1590dSMartin KaFai Lau 
457bd1590dSMartin KaFai Lau 	sk = bpf_sk_fullsock(sk);
467bd1590dSMartin KaFai Lau 	if (!sk)
477bd1590dSMartin KaFai Lau 		return -1;
487bd1590dSMartin KaFai Lau 
497bd1590dSMartin KaFai Lau 	a = bpf_kfunc_call_test1((struct sock *)sk, 1, a | 2, 3, a | 4);
507bd1590dSMartin KaFai Lau 	ret = a >> 32;   /* ret should be 2 */
517bd1590dSMartin KaFai Lau 	ret += (__u32)a; /* ret should be 12 */
527bd1590dSMartin KaFai Lau 
537bd1590dSMartin KaFai Lau 	return ret;
547bd1590dSMartin KaFai Lau }
557bd1590dSMartin KaFai Lau 
56c1ff181fSKumar Kartikeya Dwivedi SEC("tc")
57c1ff181fSKumar Kartikeya Dwivedi int kfunc_call_test_ref_btf_id(struct __sk_buff *skb)
58c1ff181fSKumar Kartikeya Dwivedi {
59c1ff181fSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *pt;
60c1ff181fSKumar Kartikeya Dwivedi 	unsigned long s = 0;
61c1ff181fSKumar Kartikeya Dwivedi 	int ret = 0;
62c1ff181fSKumar Kartikeya Dwivedi 
63c1ff181fSKumar Kartikeya Dwivedi 	pt = bpf_kfunc_call_test_acquire(&s);
64c1ff181fSKumar Kartikeya Dwivedi 	if (pt) {
65c1ff181fSKumar Kartikeya Dwivedi 		if (pt->a != 42 || pt->b != 108)
66c1ff181fSKumar Kartikeya Dwivedi 			ret = -1;
67c1ff181fSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(pt);
68c1ff181fSKumar Kartikeya Dwivedi 	}
69c1ff181fSKumar Kartikeya Dwivedi 	return ret;
70c1ff181fSKumar Kartikeya Dwivedi }
71c1ff181fSKumar Kartikeya Dwivedi 
72c1ff181fSKumar Kartikeya Dwivedi SEC("tc")
73c1ff181fSKumar Kartikeya Dwivedi int kfunc_call_test_pass(struct __sk_buff *skb)
74c1ff181fSKumar Kartikeya Dwivedi {
75c1ff181fSKumar Kartikeya Dwivedi 	struct prog_test_pass1 p1 = {};
76c1ff181fSKumar Kartikeya Dwivedi 	struct prog_test_pass2 p2 = {};
77c1ff181fSKumar Kartikeya Dwivedi 	short a = 0;
78c1ff181fSKumar Kartikeya Dwivedi 	__u64 b = 0;
79c1ff181fSKumar Kartikeya Dwivedi 	long c = 0;
80c1ff181fSKumar Kartikeya Dwivedi 	char d = 0;
81c1ff181fSKumar Kartikeya Dwivedi 	int e = 0;
82c1ff181fSKumar Kartikeya Dwivedi 
83c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_pass_ctx(skb);
84c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_pass1(&p1);
85c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_pass2(&p2);
86c1ff181fSKumar Kartikeya Dwivedi 
87c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&a, sizeof(a));
88c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&b, sizeof(b));
89c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&c, sizeof(c));
90c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&d, sizeof(d));
91c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_pass1(&e, sizeof(e));
92c1ff181fSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_mem_len_fail2(&b, -1);
93c1ff181fSKumar Kartikeya Dwivedi 
94c1ff181fSKumar Kartikeya Dwivedi 	return 0;
95c1ff181fSKumar Kartikeya Dwivedi }
96c1ff181fSKumar Kartikeya Dwivedi 
97fb66223aSBenjamin Tissoires struct syscall_test_args {
98fb66223aSBenjamin Tissoires 	__u8 data[16];
99fb66223aSBenjamin Tissoires 	size_t size;
100fb66223aSBenjamin Tissoires };
101fb66223aSBenjamin Tissoires 
102fb66223aSBenjamin Tissoires SEC("syscall")
103fb66223aSBenjamin Tissoires int kfunc_syscall_test(struct syscall_test_args *args)
104fb66223aSBenjamin Tissoires {
105fb66223aSBenjamin Tissoires 	const long size = args->size;
106fb66223aSBenjamin Tissoires 
107fb66223aSBenjamin Tissoires 	if (size > sizeof(args->data))
108fb66223aSBenjamin Tissoires 		return -7; /* -E2BIG */
109fb66223aSBenjamin Tissoires 
110fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(&args->data, sizeof(args->data));
111fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(&args->data, sizeof(*args));
112fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(&args->data, size);
113fb66223aSBenjamin Tissoires 
114fb66223aSBenjamin Tissoires 	return 0;
115fb66223aSBenjamin Tissoires }
116fb66223aSBenjamin Tissoires 
117fb66223aSBenjamin Tissoires SEC("syscall")
118fb66223aSBenjamin Tissoires int kfunc_syscall_test_null(struct syscall_test_args *args)
119fb66223aSBenjamin Tissoires {
120fb66223aSBenjamin Tissoires 	/* Must be called with args as a NULL pointer
121fb66223aSBenjamin Tissoires 	 * we do not check for it to have the verifier consider that
122fb66223aSBenjamin Tissoires 	 * the pointer might not be null, and so we can load it.
123fb66223aSBenjamin Tissoires 	 *
124fb66223aSBenjamin Tissoires 	 * So the following can not be added:
125fb66223aSBenjamin Tissoires 	 *
126fb66223aSBenjamin Tissoires 	 * if (args)
127fb66223aSBenjamin Tissoires 	 *      return -22;
128fb66223aSBenjamin Tissoires 	 */
129fb66223aSBenjamin Tissoires 
130fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(args, 0);
131fb66223aSBenjamin Tissoires 
132fb66223aSBenjamin Tissoires 	return 0;
133fb66223aSBenjamin Tissoires }
134fb66223aSBenjamin Tissoires 
135*22ed8d5aSBenjamin Tissoires SEC("tc")
136*22ed8d5aSBenjamin Tissoires int kfunc_call_test_get_mem(struct __sk_buff *skb)
137*22ed8d5aSBenjamin Tissoires {
138*22ed8d5aSBenjamin Tissoires 	struct prog_test_ref_kfunc *pt;
139*22ed8d5aSBenjamin Tissoires 	unsigned long s = 0;
140*22ed8d5aSBenjamin Tissoires 	int *p = NULL;
141*22ed8d5aSBenjamin Tissoires 	int ret = 0;
142*22ed8d5aSBenjamin Tissoires 
143*22ed8d5aSBenjamin Tissoires 	pt = bpf_kfunc_call_test_acquire(&s);
144*22ed8d5aSBenjamin Tissoires 	if (pt) {
145*22ed8d5aSBenjamin Tissoires 		p = bpf_kfunc_call_test_get_rdwr_mem(pt, 2 * sizeof(int));
146*22ed8d5aSBenjamin Tissoires 		if (p) {
147*22ed8d5aSBenjamin Tissoires 			p[0] = 42;
148*22ed8d5aSBenjamin Tissoires 			ret = p[1]; /* 108 */
149*22ed8d5aSBenjamin Tissoires 		} else {
150*22ed8d5aSBenjamin Tissoires 			ret = -1;
151*22ed8d5aSBenjamin Tissoires 		}
152*22ed8d5aSBenjamin Tissoires 
153*22ed8d5aSBenjamin Tissoires 		if (ret >= 0) {
154*22ed8d5aSBenjamin Tissoires 			p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int));
155*22ed8d5aSBenjamin Tissoires 			if (p)
156*22ed8d5aSBenjamin Tissoires 				ret = p[0]; /* 42 */
157*22ed8d5aSBenjamin Tissoires 			else
158*22ed8d5aSBenjamin Tissoires 				ret = -1;
159*22ed8d5aSBenjamin Tissoires 		}
160*22ed8d5aSBenjamin Tissoires 
161*22ed8d5aSBenjamin Tissoires 		bpf_kfunc_call_test_release(pt);
162*22ed8d5aSBenjamin Tissoires 	}
163*22ed8d5aSBenjamin Tissoires 	return ret;
164*22ed8d5aSBenjamin Tissoires }
165*22ed8d5aSBenjamin Tissoires 
1667bd1590dSMartin KaFai Lau char _license[] SEC("license") = "GPL";
167