1fb66223aSBenjamin Tissoires // SPDX-License-Identifier: GPL-2.0
2fb66223aSBenjamin Tissoires /* Copyright (c) 2021 Facebook */
3fb66223aSBenjamin Tissoires #include <vmlinux.h>
4fb66223aSBenjamin Tissoires #include <bpf/bpf_helpers.h>
5*8e9af821SJiri Olsa #include "../bpf_testmod/bpf_testmod_kfunc.h"
6fb66223aSBenjamin Tissoires 
7fb66223aSBenjamin Tissoires struct syscall_test_args {
8fb66223aSBenjamin Tissoires 	__u8 data[16];
9fb66223aSBenjamin Tissoires 	size_t size;
10fb66223aSBenjamin Tissoires };
11fb66223aSBenjamin Tissoires 
12fb66223aSBenjamin Tissoires SEC("?syscall")
kfunc_syscall_test_fail(struct syscall_test_args * args)13fb66223aSBenjamin Tissoires int kfunc_syscall_test_fail(struct syscall_test_args *args)
14fb66223aSBenjamin Tissoires {
15fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(&args->data, sizeof(*args) + 1);
16fb66223aSBenjamin Tissoires 
17fb66223aSBenjamin Tissoires 	return 0;
18fb66223aSBenjamin Tissoires }
19fb66223aSBenjamin Tissoires 
20fb66223aSBenjamin Tissoires SEC("?syscall")
kfunc_syscall_test_null_fail(struct syscall_test_args * args)21fb66223aSBenjamin Tissoires int kfunc_syscall_test_null_fail(struct syscall_test_args *args)
22fb66223aSBenjamin Tissoires {
23fb66223aSBenjamin Tissoires 	/* Must be called with args as a NULL pointer
24fb66223aSBenjamin Tissoires 	 * we do not check for it to have the verifier consider that
25fb66223aSBenjamin Tissoires 	 * the pointer might not be null, and so we can load it.
26fb66223aSBenjamin Tissoires 	 *
27fb66223aSBenjamin Tissoires 	 * So the following can not be added:
28fb66223aSBenjamin Tissoires 	 *
29fb66223aSBenjamin Tissoires 	 * if (args)
30fb66223aSBenjamin Tissoires 	 *      return -22;
31fb66223aSBenjamin Tissoires 	 */
32fb66223aSBenjamin Tissoires 
33fb66223aSBenjamin Tissoires 	bpf_kfunc_call_test_mem_len_pass1(args, sizeof(*args));
34fb66223aSBenjamin Tissoires 
35fb66223aSBenjamin Tissoires 	return 0;
36fb66223aSBenjamin Tissoires }
37fb66223aSBenjamin Tissoires 
3822ed8d5aSBenjamin Tissoires SEC("?tc")
kfunc_call_test_get_mem_fail_rdonly(struct __sk_buff * skb)3922ed8d5aSBenjamin Tissoires int kfunc_call_test_get_mem_fail_rdonly(struct __sk_buff *skb)
4022ed8d5aSBenjamin Tissoires {
4122ed8d5aSBenjamin Tissoires 	struct prog_test_ref_kfunc *pt;
4222ed8d5aSBenjamin Tissoires 	unsigned long s = 0;
4322ed8d5aSBenjamin Tissoires 	int *p = NULL;
4422ed8d5aSBenjamin Tissoires 	int ret = 0;
4522ed8d5aSBenjamin Tissoires 
4622ed8d5aSBenjamin Tissoires 	pt = bpf_kfunc_call_test_acquire(&s);
4722ed8d5aSBenjamin Tissoires 	if (pt) {
4822ed8d5aSBenjamin Tissoires 		p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int));
4922ed8d5aSBenjamin Tissoires 		if (p)
5022ed8d5aSBenjamin Tissoires 			p[0] = 42; /* this is a read-only buffer, so -EACCES */
5122ed8d5aSBenjamin Tissoires 		else
5222ed8d5aSBenjamin Tissoires 			ret = -1;
5322ed8d5aSBenjamin Tissoires 
5422ed8d5aSBenjamin Tissoires 		bpf_kfunc_call_test_release(pt);
5522ed8d5aSBenjamin Tissoires 	}
5622ed8d5aSBenjamin Tissoires 	return ret;
5722ed8d5aSBenjamin Tissoires }
5822ed8d5aSBenjamin Tissoires 
5922ed8d5aSBenjamin Tissoires SEC("?tc")
kfunc_call_test_get_mem_fail_use_after_free(struct __sk_buff * skb)6022ed8d5aSBenjamin Tissoires int kfunc_call_test_get_mem_fail_use_after_free(struct __sk_buff *skb)
6122ed8d5aSBenjamin Tissoires {
6222ed8d5aSBenjamin Tissoires 	struct prog_test_ref_kfunc *pt;
6322ed8d5aSBenjamin Tissoires 	unsigned long s = 0;
6422ed8d5aSBenjamin Tissoires 	int *p = NULL;
6522ed8d5aSBenjamin Tissoires 	int ret = 0;
6622ed8d5aSBenjamin Tissoires 
6722ed8d5aSBenjamin Tissoires 	pt = bpf_kfunc_call_test_acquire(&s);
6822ed8d5aSBenjamin Tissoires 	if (pt) {
6922ed8d5aSBenjamin Tissoires 		p = bpf_kfunc_call_test_get_rdwr_mem(pt, 2 * sizeof(int));
7022ed8d5aSBenjamin Tissoires 		if (p) {
7122ed8d5aSBenjamin Tissoires 			p[0] = 42;
7222ed8d5aSBenjamin Tissoires 			ret = p[1]; /* 108 */
7322ed8d5aSBenjamin Tissoires 		} else {
7422ed8d5aSBenjamin Tissoires 			ret = -1;
7522ed8d5aSBenjamin Tissoires 		}
7622ed8d5aSBenjamin Tissoires 
7722ed8d5aSBenjamin Tissoires 		bpf_kfunc_call_test_release(pt);
7822ed8d5aSBenjamin Tissoires 	}
7922ed8d5aSBenjamin Tissoires 	if (p)
8022ed8d5aSBenjamin Tissoires 		ret = p[0]; /* p is not valid anymore */
8122ed8d5aSBenjamin Tissoires 
8222ed8d5aSBenjamin Tissoires 	return ret;
8322ed8d5aSBenjamin Tissoires }
8422ed8d5aSBenjamin Tissoires 
8522ed8d5aSBenjamin Tissoires SEC("?tc")
kfunc_call_test_get_mem_fail_oob(struct __sk_buff * skb)8622ed8d5aSBenjamin Tissoires int kfunc_call_test_get_mem_fail_oob(struct __sk_buff *skb)
8722ed8d5aSBenjamin Tissoires {
8822ed8d5aSBenjamin Tissoires 	struct prog_test_ref_kfunc *pt;
8922ed8d5aSBenjamin Tissoires 	unsigned long s = 0;
9022ed8d5aSBenjamin Tissoires 	int *p = NULL;
9122ed8d5aSBenjamin Tissoires 	int ret = 0;
9222ed8d5aSBenjamin Tissoires 
9322ed8d5aSBenjamin Tissoires 	pt = bpf_kfunc_call_test_acquire(&s);
9422ed8d5aSBenjamin Tissoires 	if (pt) {
9522ed8d5aSBenjamin Tissoires 		p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int));
9622ed8d5aSBenjamin Tissoires 		if (p)
9722ed8d5aSBenjamin Tissoires 			ret = p[2 * sizeof(int)]; /* oob access, so -EACCES */
9822ed8d5aSBenjamin Tissoires 		else
9922ed8d5aSBenjamin Tissoires 			ret = -1;
10022ed8d5aSBenjamin Tissoires 
10122ed8d5aSBenjamin Tissoires 		bpf_kfunc_call_test_release(pt);
10222ed8d5aSBenjamin Tissoires 	}
10322ed8d5aSBenjamin Tissoires 	return ret;
10422ed8d5aSBenjamin Tissoires }
10522ed8d5aSBenjamin Tissoires 
10622ed8d5aSBenjamin Tissoires int not_const_size = 2 * sizeof(int);
10722ed8d5aSBenjamin Tissoires 
10822ed8d5aSBenjamin Tissoires SEC("?tc")
kfunc_call_test_get_mem_fail_not_const(struct __sk_buff * skb)10922ed8d5aSBenjamin Tissoires int kfunc_call_test_get_mem_fail_not_const(struct __sk_buff *skb)
11022ed8d5aSBenjamin Tissoires {
11122ed8d5aSBenjamin Tissoires 	struct prog_test_ref_kfunc *pt;
11222ed8d5aSBenjamin Tissoires 	unsigned long s = 0;
11322ed8d5aSBenjamin Tissoires 	int *p = NULL;
11422ed8d5aSBenjamin Tissoires 	int ret = 0;
11522ed8d5aSBenjamin Tissoires 
11622ed8d5aSBenjamin Tissoires 	pt = bpf_kfunc_call_test_acquire(&s);
11722ed8d5aSBenjamin Tissoires 	if (pt) {
11822ed8d5aSBenjamin Tissoires 		p = bpf_kfunc_call_test_get_rdonly_mem(pt, not_const_size); /* non const size, -EINVAL */
11922ed8d5aSBenjamin Tissoires 		if (p)
12022ed8d5aSBenjamin Tissoires 			ret = p[0];
12122ed8d5aSBenjamin Tissoires 		else
12222ed8d5aSBenjamin Tissoires 			ret = -1;
12322ed8d5aSBenjamin Tissoires 
12422ed8d5aSBenjamin Tissoires 		bpf_kfunc_call_test_release(pt);
12522ed8d5aSBenjamin Tissoires 	}
12622ed8d5aSBenjamin Tissoires 	return ret;
12722ed8d5aSBenjamin Tissoires }
12822ed8d5aSBenjamin Tissoires 
12922ed8d5aSBenjamin Tissoires SEC("?tc")
kfunc_call_test_mem_acquire_fail(struct __sk_buff * skb)13022ed8d5aSBenjamin Tissoires int kfunc_call_test_mem_acquire_fail(struct __sk_buff *skb)
13122ed8d5aSBenjamin Tissoires {
13222ed8d5aSBenjamin Tissoires 	struct prog_test_ref_kfunc *pt;
13322ed8d5aSBenjamin Tissoires 	unsigned long s = 0;
13422ed8d5aSBenjamin Tissoires 	int *p = NULL;
13522ed8d5aSBenjamin Tissoires 	int ret = 0;
13622ed8d5aSBenjamin Tissoires 
13722ed8d5aSBenjamin Tissoires 	pt = bpf_kfunc_call_test_acquire(&s);
13822ed8d5aSBenjamin Tissoires 	if (pt) {
13922ed8d5aSBenjamin Tissoires 		/* we are failing on this one, because we are not acquiring a PTR_TO_BTF_ID (a struct ptr) */
14022ed8d5aSBenjamin Tissoires 		p = bpf_kfunc_call_test_acq_rdonly_mem(pt, 2 * sizeof(int));
14122ed8d5aSBenjamin Tissoires 		if (p)
14222ed8d5aSBenjamin Tissoires 			ret = p[0];
14322ed8d5aSBenjamin Tissoires 		else
14422ed8d5aSBenjamin Tissoires 			ret = -1;
14522ed8d5aSBenjamin Tissoires 
14622ed8d5aSBenjamin Tissoires 		bpf_kfunc_call_int_mem_release(p);
14722ed8d5aSBenjamin Tissoires 
14822ed8d5aSBenjamin Tissoires 		bpf_kfunc_call_test_release(pt);
14922ed8d5aSBenjamin Tissoires 	}
15022ed8d5aSBenjamin Tissoires 	return ret;
15122ed8d5aSBenjamin Tissoires }
15222ed8d5aSBenjamin Tissoires 
153fb66223aSBenjamin Tissoires char _license[] SEC("license") = "GPL";
154